mygithub.libinneed.workers.dev/stackitcloud/stackit-cli
Advanced tools
+3
-3
@@ -8,3 +8,3 @@ module github.com/stackitcloud/stackit-cli | ||
| github.com/goccy/go-yaml v1.19.2 | ||
| github.com/golang-jwt/jwt/v5 v5.3.0 | ||
| github.com/golang-jwt/jwt/v5 v5.3.1 | ||
| github.com/google/go-cmp v0.7.0 | ||
@@ -19,3 +19,3 @@ github.com/google/uuid v1.6.0 | ||
| github.com/spf13/viper v1.21.0 | ||
| github.com/stackitcloud/stackit-sdk-go/core v0.20.1 | ||
| github.com/stackitcloud/stackit-sdk-go/core v0.21.1 | ||
| github.com/stackitcloud/stackit-sdk-go/services/alb v0.9.0 | ||
@@ -278,3 +278,3 @@ github.com/stackitcloud/stackit-sdk-go/services/authorization v0.11.0 | ||
| github.com/stackitcloud/stackit-sdk-go/services/redis v0.25.3 | ||
| github.com/stackitcloud/stackit-sdk-go/services/sfs v0.2.0 | ||
| github.com/stackitcloud/stackit-sdk-go/services/sfs v0.3.0 | ||
| github.com/subosito/gotenv v1.6.0 // indirect | ||
@@ -281,0 +281,0 @@ golang.org/x/sys v0.40.0 // indirect |
@@ -7,5 +7,8 @@ package auth | ||
| "crypto/x509" | ||
| "encoding/json" | ||
| "encoding/pem" | ||
| "fmt" | ||
| "io" | ||
| "net/http" | ||
| "net/http/httptest" | ||
| "strconv" | ||
@@ -239,55 +242,25 @@ "testing" | ||
| tests := []struct { | ||
| description string | ||
| accessTokenSet bool | ||
| refreshToken string | ||
| saKey string | ||
| privateKeySet bool | ||
| tokenEndpoint string | ||
| isValid bool | ||
| description string | ||
| saKey string | ||
| privateKeySet bool | ||
| isValid bool | ||
| }{ | ||
| { | ||
| description: "base", | ||
| accessTokenSet: true, | ||
| refreshToken: "refresh_token", | ||
| saKey: testServiceAccountKey, | ||
| privateKeySet: true, | ||
| tokenEndpoint: "token_url", | ||
| isValid: true, | ||
| description: "base", | ||
| saKey: testServiceAccountKey, | ||
| privateKeySet: true, | ||
| isValid: true, | ||
| }, | ||
| { | ||
| description: "invalid_service_account_key", | ||
| accessTokenSet: true, | ||
| refreshToken: "refresh_token", | ||
| saKey: "", | ||
| privateKeySet: true, | ||
| tokenEndpoint: "token_url", | ||
| isValid: false, | ||
| description: "invalid_service_account_key", | ||
| saKey: "", | ||
| privateKeySet: true, | ||
| isValid: false, | ||
| }, | ||
| { | ||
| description: "invalid_private_key", | ||
| accessTokenSet: true, | ||
| refreshToken: "refresh_token", | ||
| saKey: testServiceAccountKey, | ||
| privateKeySet: false, | ||
| tokenEndpoint: "token_url", | ||
| isValid: false, | ||
| description: "no_private_key_set", | ||
| saKey: testServiceAccountKey, | ||
| privateKeySet: false, | ||
| isValid: false, | ||
| }, | ||
| { | ||
| description: "invalid_access_token", | ||
| accessTokenSet: false, | ||
| refreshToken: "refresh_token", | ||
| saKey: testServiceAccountKey, | ||
| privateKeySet: true, | ||
| tokenEndpoint: "token_url", | ||
| isValid: false, | ||
| }, | ||
| { | ||
| description: "empty_refresh_token", | ||
| accessTokenSet: false, | ||
| refreshToken: "", | ||
| saKey: testServiceAccountKey, | ||
| privateKeySet: true, | ||
| tokenEndpoint: "token_url", | ||
| isValid: false, | ||
| }, | ||
| } | ||
@@ -302,9 +275,7 @@ | ||
| var err error | ||
| if tt.accessTokenSet { | ||
| accessTokenJWT := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.RegisteredClaims{ | ||
| ExpiresAt: jwt.NewNumericDate(timestamp)}) | ||
| accessToken, err = accessTokenJWT.SignedString(testSigningKey) | ||
| if err != nil { | ||
| t.Fatalf("Get test access token as string: %s", err) | ||
| } | ||
| accessTokenJWT := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.RegisteredClaims{ | ||
| ExpiresAt: jwt.NewNumericDate(timestamp)}) | ||
| accessToken, err = accessTokenJWT.SignedString(testSigningKey) | ||
| if err != nil { | ||
| t.Fatalf("Get test access token as string: %s", err) | ||
| } | ||
@@ -319,5 +290,24 @@ if tt.privateKeySet { | ||
| authFields[ACCESS_TOKEN] = accessToken | ||
| authFields[REFRESH_TOKEN] = tt.refreshToken | ||
| authFields[SERVICE_ACCOUNT_KEY] = tt.saKey | ||
| authFields[TOKEN_CUSTOM_ENDPOINT] = tt.tokenEndpoint | ||
| // Mock server to avoid HTTP calls | ||
| server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { | ||
| w.WriteHeader(http.StatusOK) | ||
| resp := clients.TokenResponseBody{ | ||
| AccessToken: accessToken, | ||
| ExpiresIn: 3600, | ||
| TokenType: "Bearer", | ||
| } | ||
| jsonResp, err := json.Marshal(resp) | ||
| if err != nil { | ||
| t.Fatalf("Failed to marshal json: %v", err) | ||
| } | ||
| _, err = w.Write(jsonResp) | ||
| if err != nil { | ||
| t.Fatalf("Failed to write response: %v", err) | ||
| } | ||
| })) | ||
| defer server.Close() | ||
| authFields[TOKEN_CUSTOM_ENDPOINT] = server.URL | ||
| err = SetAuthFieldMap(authFields) | ||
@@ -329,3 +319,10 @@ if err != nil { | ||
| keyFlowWithStorage, err := initKeyFlowWithStorage() | ||
| if err != nil { | ||
| if !tt.isValid { | ||
| return | ||
| } | ||
| t.Fatalf("Expected no error but error was returned: %v", err) | ||
| } | ||
| getAccessToken, err := keyFlowWithStorage.keyFlow.GetAccessToken() | ||
| if !tt.isValid { | ||
@@ -339,12 +336,5 @@ if err == nil { | ||
| } | ||
| expectedToken := &clients.TokenResponseBody{ | ||
| AccessToken: accessToken, | ||
| ExpiresIn: int(timestamp.Unix()), | ||
| RefreshToken: tt.refreshToken, | ||
| Scope: "", | ||
| TokenType: "Bearer", | ||
| if !cmp.Equal(accessToken, getAccessToken) { | ||
| t.Errorf("The returned result is wrong. Expected %+v, got %+v", accessToken, getAccessToken) | ||
| } | ||
| if !cmp.Equal(*expectedToken, keyFlowWithStorage.keyFlow.GetToken()) { | ||
| t.Errorf("The returned result is wrong. Expected %+v, got %+v", expectedToken, keyFlowWithStorage.keyFlow.GetToken()) | ||
| } | ||
| } | ||
@@ -351,0 +341,0 @@ }) |
@@ -17,3 +17,2 @@ package auth | ||
| GetConfig() clients.KeyFlowConfig | ||
| GetToken() clients.TokenResponseBody | ||
| RoundTrip(*http.Request) (*http.Response, error) | ||
@@ -36,3 +35,3 @@ } | ||
| // authenticates the CLI accordingly and store the credentials. | ||
| // For the key flow, it fetches an access and refresh token from the Service Account API. | ||
| // For the key flow, it fetches an access token from the Service Account API. | ||
| // For the token flow, it just stores the provided token and doesn't check if it is valid. | ||
@@ -61,3 +60,2 @@ // It returns the email associated with the service account | ||
| authFields[ACCESS_TOKEN] = accessToken | ||
| authFields[REFRESH_TOKEN] = flow.GetToken().RefreshToken | ||
| authFields[SERVICE_ACCOUNT_KEY] = string(saKeyBytes) | ||
@@ -106,4 +104,2 @@ authFields[PRIVATE_KEY] = flow.GetConfig().PrivateKey | ||
| authFields := map[authFieldKey]string{ | ||
| ACCESS_TOKEN: "", | ||
| REFRESH_TOKEN: "", | ||
| SERVICE_ACCOUNT_KEY: "", | ||
@@ -117,8 +113,2 @@ PRIVATE_KEY: "", | ||
| } | ||
| if authFields[ACCESS_TOKEN] == "" { | ||
| return nil, fmt.Errorf("access token not set") | ||
| } | ||
| if authFields[REFRESH_TOKEN] == "" { | ||
| return nil, fmt.Errorf("refresh token not set") | ||
| } | ||
@@ -142,6 +132,2 @@ var serviceAccountKey = &clients.ServiceAccountKeyResponse{} | ||
| } | ||
| err = keyFlow.SetToken(authFields[ACCESS_TOKEN], authFields[REFRESH_TOKEN]) | ||
| if err != nil { | ||
| return nil, fmt.Errorf("set access and refresh token: %w", err) | ||
| } | ||
@@ -155,12 +141,13 @@ // create keyFlowWithStorage roundtripper that stores the credentials after executing a request | ||
| // The keyFlowWithStorage Roundtrip executes the keyFlow roundtrip and then stores the access and refresh tokens | ||
| // The keyFlowWithStorage Roundtrip executes the keyFlow roundtrip and then stores the access token | ||
| func (kf *keyFlowWithStorage) RoundTrip(req *http.Request) (*http.Response, error) { | ||
| resp, err := kf.keyFlow.RoundTrip(req) | ||
| token := kf.keyFlow.GetToken() | ||
| accessToken := token.AccessToken | ||
| refreshToken := token.RefreshToken | ||
| accessToken, getTokenErr := kf.keyFlow.GetAccessToken() | ||
| if getTokenErr != nil { | ||
| return nil, fmt.Errorf("get access token: %w", getTokenErr) | ||
| } | ||
| tokenValues := map[authFieldKey]string{ | ||
| ACCESS_TOKEN: accessToken, | ||
| REFRESH_TOKEN: refreshToken, | ||
| ACCESS_TOKEN: accessToken, | ||
| } | ||
@@ -170,3 +157,7 @@ | ||
| if storageErr != nil { | ||
| return nil, fmt.Errorf("set access and refresh token in the storage: %w", err) | ||
| // If the request was successful, but storing the token failed we still return the response and a nil error | ||
| if err == nil { | ||
| return resp, nil | ||
| } | ||
| return nil, fmt.Errorf("set access token in the storage: %w", err) | ||
| } | ||
@@ -173,0 +164,0 @@ |
Sorry, the diff of this file is too big to display