-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
82 changed files
with
12,154 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
102 changes: 102 additions & 0 deletions
102
internal/cmd/auth/activate-service-account/activate_service_account.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
package activateserviceaccount | ||
|
||
import ( | ||
"fmt" | ||
|
||
"github.com/stackitcloud/stackit-cli/internal/pkg/auth" | ||
"github.com/stackitcloud/stackit-cli/internal/pkg/utils" | ||
|
||
"github.com/spf13/cobra" | ||
sdkAuth "github.com/stackitcloud/stackit-sdk-go/core/auth" | ||
sdkConfig "github.com/stackitcloud/stackit-sdk-go/core/config" | ||
) | ||
|
||
const ( | ||
serviceAccountTokenFlag = "service-account-token" | ||
serviceAccountKeyPathFlag = "service-account-key-path" | ||
privateKeyPathFlag = "private-key-path" | ||
tokenCustomEndpointFlag = "token-custom-endpoint" | ||
jwksCustomEndpointFlag = "jwks-custom-endpoint" | ||
) | ||
|
||
type flagModel struct { | ||
ServiceAccountToken string | ||
ServiceAccountKeyPath string | ||
PrivateKeyPath string | ||
TokenCustomEndpoint string | ||
JwksCustomEndpoint string | ||
} | ||
|
||
var Cmd = &cobra.Command{ | ||
Use: "activate-service-account", | ||
Short: "Activate service account authentication", | ||
Long: "Activate authentication using service account credentials.\nFor more details on how to configure your service account, check the Authentication section on our documentation (LINK HERE README)", | ||
Example: `$ stackit auth activate-service-account --service-account-key-path path/to/service_account_key.json --private-key-path path/to/private_key.pem`, | ||
RunE: func(cmd *cobra.Command, args []string) error { | ||
model := parseFlags(cmd) | ||
|
||
err := storeFlags(model) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
cfg := &sdkConfig.Configuration{ | ||
Token: model.ServiceAccountToken, | ||
ServiceAccountKeyPath: model.ServiceAccountKeyPath, | ||
PrivateKeyPath: model.PrivateKeyPath, | ||
TokenCustomUrl: model.TokenCustomEndpoint, | ||
JWKSCustomUrl: model.JwksCustomEndpoint, | ||
} | ||
|
||
// Setup authentication based on the provided credentials and the environment | ||
// Initializes the authentication flow | ||
rt, err := sdkAuth.SetupAuth(cfg) | ||
if err != nil { | ||
return fmt.Errorf("set up authentication: %w", err) | ||
} | ||
|
||
// Authenticates the service account and stores credentials | ||
email, err := auth.AuthenticateServiceAccount(rt) | ||
if err != nil { | ||
return fmt.Errorf("authenticate service account: %w", err) | ||
} | ||
|
||
fmt.Printf("You have been successfully authenticated to the STACKIT CLI!\nService account email: %s\n", email) | ||
|
||
return nil | ||
}, | ||
} | ||
|
||
func init() { | ||
configureFlags(Cmd) | ||
} | ||
|
||
func configureFlags(cmd *cobra.Command) { | ||
cmd.Flags().String(serviceAccountTokenFlag, "", "Service account long-lived access token") | ||
cmd.Flags().String(serviceAccountKeyPathFlag, "", "Service account key path") | ||
cmd.Flags().String(privateKeyPathFlag, "", "RSA private key path") | ||
cmd.Flags().String(tokenCustomEndpointFlag, "", "Custom endpoint for the token API, which is used to request access tokens when the service-account authentication is activated") | ||
cmd.Flags().String(jwksCustomEndpointFlag, "", "Custom endpoint for the jwks API, which is used to get the json web key sets (jwks) to validate tokens when the service-account authentication is activated") | ||
} | ||
|
||
func parseFlags(cmd *cobra.Command) *flagModel { | ||
return &flagModel{ | ||
ServiceAccountToken: utils.FlagToStringValue(cmd, serviceAccountTokenFlag), | ||
ServiceAccountKeyPath: utils.FlagToStringValue(cmd, serviceAccountKeyPathFlag), | ||
PrivateKeyPath: utils.FlagToStringValue(cmd, privateKeyPathFlag), | ||
TokenCustomEndpoint: utils.FlagToStringValue(cmd, tokenCustomEndpointFlag), | ||
JwksCustomEndpoint: utils.FlagToStringValue(cmd, jwksCustomEndpointFlag), | ||
} | ||
} | ||
|
||
func storeFlags(model *flagModel) error { | ||
err := auth.SetAuthField(auth.TOKEN_CUSTOM_ENDPOINT, model.TokenCustomEndpoint) | ||
if err != nil { | ||
return fmt.Errorf("set %s: %w", auth.TOKEN_CUSTOM_ENDPOINT, err) | ||
} | ||
err = auth.SetAuthField(auth.JWKS_CUSTOM_ENDPOINT, model.JwksCustomEndpoint) | ||
if err != nil { | ||
return fmt.Errorf("set %s: %w", auth.JWKS_CUSTOM_ENDPOINT, err) | ||
} | ||
return nil | ||
} |
117 changes: 117 additions & 0 deletions
117
internal/cmd/auth/activate-service-account/activate_service_account_test.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
package activateserviceaccount | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/google/go-cmp/cmp" | ||
"github.com/spf13/cobra" | ||
) | ||
|
||
func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { | ||
flagValues := map[string]string{ | ||
serviceAccountTokenFlag: "token", | ||
serviceAccountKeyPathFlag: "sa_key", | ||
privateKeyPathFlag: "private_key", | ||
tokenCustomEndpointFlag: "token_url", | ||
jwksCustomEndpointFlag: "jwks_url", | ||
} | ||
for _, mod := range mods { | ||
mod(flagValues) | ||
} | ||
return flagValues | ||
} | ||
|
||
func fixtureFlagModel(mods ...func(model *flagModel)) *flagModel { | ||
model := &flagModel{ | ||
ServiceAccountToken: "token", | ||
ServiceAccountKeyPath: "sa_key", | ||
PrivateKeyPath: "private_key", | ||
TokenCustomEndpoint: "token_url", | ||
JwksCustomEndpoint: "jwks_url", | ||
} | ||
for _, mod := range mods { | ||
mod(model) | ||
} | ||
return model | ||
} | ||
|
||
func TestParseFlags(t *testing.T) { | ||
tests := []struct { | ||
description string | ||
flagValues map[string]string | ||
isValid bool | ||
expectedModel *flagModel | ||
}{ | ||
{ | ||
description: "base", | ||
flagValues: fixtureFlagValues(), | ||
isValid: true, | ||
expectedModel: fixtureFlagModel(), | ||
}, | ||
{ | ||
description: "no values", | ||
flagValues: map[string]string{}, | ||
isValid: true, | ||
expectedModel: &flagModel{ | ||
ServiceAccountToken: "", | ||
ServiceAccountKeyPath: "", | ||
PrivateKeyPath: "", | ||
TokenCustomEndpoint: "", | ||
JwksCustomEndpoint: "", | ||
}, | ||
}, | ||
{ | ||
description: "zero values", | ||
flagValues: map[string]string{ | ||
serviceAccountTokenFlag: "", | ||
serviceAccountKeyPathFlag: "", | ||
privateKeyPathFlag: "", | ||
tokenCustomEndpointFlag: "", | ||
jwksCustomEndpointFlag: "", | ||
}, | ||
isValid: true, | ||
expectedModel: &flagModel{ | ||
ServiceAccountToken: "", | ||
ServiceAccountKeyPath: "", | ||
PrivateKeyPath: "", | ||
TokenCustomEndpoint: "", | ||
JwksCustomEndpoint: "", | ||
}, | ||
}, | ||
{ | ||
description: "invalid_flag", | ||
flagValues: fixtureFlagValues(func(flagValues map[string]string) { | ||
flagValues["test_flag"] = "test" | ||
}), | ||
isValid: false, | ||
}, | ||
} | ||
|
||
for _, tt := range tests { | ||
t.Run(tt.description, func(t *testing.T) { | ||
cmd := &cobra.Command{} | ||
|
||
configureFlags(cmd) | ||
|
||
for flag, value := range tt.flagValues { | ||
err := cmd.Flags().Set(flag, value) | ||
if err != nil { | ||
if !tt.isValid { | ||
return | ||
} | ||
t.Fatalf("setting flag --%s=%s: %v", flag, value, err) | ||
} | ||
} | ||
|
||
model := parseFlags(cmd) | ||
|
||
if !tt.isValid { | ||
t.Fatalf("did not fail on invalid input") | ||
} | ||
diff := cmp.Diff(model, tt.expectedModel) | ||
if diff != "" { | ||
t.Fatalf("Data does not match: %s", diff) | ||
} | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
package auth | ||
|
||
import ( | ||
activateserviceaccount "github.com/stackitcloud/stackit-cli/internal/cmd/auth/activate-service-account" | ||
"github.com/stackitcloud/stackit-cli/internal/cmd/auth/login" | ||
|
||
"github.com/spf13/cobra" | ||
) | ||
|
||
var Cmd = &cobra.Command{ | ||
Use: "auth", | ||
Short: "Provides authentication functionality", | ||
Long: "Provides authentication functionality", | ||
Example: `$ stackit auth login`, | ||
} | ||
|
||
func init() { | ||
// Add all direct child commands | ||
Cmd.AddCommand(login.Cmd) | ||
Cmd.AddCommand(activateserviceaccount.Cmd) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
package login | ||
|
||
import ( | ||
"fmt" | ||
"os" | ||
|
||
"github.com/stackitcloud/stackit-cli/internal/pkg/auth" | ||
|
||
"github.com/spf13/cobra" | ||
) | ||
|
||
var Cmd = &cobra.Command{ | ||
Use: "login", | ||
Short: "Login to the provider", | ||
Long: "Login to the provider", | ||
Example: `$ stackit auth login`, | ||
Run: func(cmd *cobra.Command, args []string) { | ||
err := auth.AuthorizeUser() | ||
if err != nil { | ||
fmt.Printf("Authorization failed: %s\n", err) | ||
os.Exit(1) | ||
} | ||
|
||
fmt.Println("Successfully logged into STACKIT CLI.") | ||
}, | ||
} | ||
|
||
func init() { | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
package config | ||
|
||
import ( | ||
"fmt" | ||
|
||
"github.com/stackitcloud/stackit-cli/internal/cmd/config/inspect" | ||
"github.com/stackitcloud/stackit-cli/internal/cmd/config/set" | ||
"github.com/stackitcloud/stackit-cli/internal/cmd/config/unset" | ||
|
||
"github.com/spf13/cobra" | ||
) | ||
|
||
var Cmd = &cobra.Command{ | ||
Use: "config", | ||
Short: "CLI configuration options", | ||
Long: "CLI configuration options", | ||
Example: fmt.Sprintf("%s\n%s\n%s", set.Cmd.Example, inspect.Cmd.Example, unset.Cmd.Example), | ||
} | ||
|
||
func init() { | ||
Cmd.AddCommand(inspect.Cmd) | ||
Cmd.AddCommand(set.Cmd) | ||
Cmd.AddCommand(unset.Cmd) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
package inspect | ||
|
||
import ( | ||
"encoding/json" | ||
"fmt" | ||
|
||
"github.com/spf13/cobra" | ||
"github.com/spf13/viper" | ||
) | ||
|
||
var Cmd = &cobra.Command{ | ||
Use: "inspect", | ||
Short: "Inspect the current CLI configuration values", | ||
Long: "Inspect the current CLI configuration values", | ||
Example: `$ stackit config inspect`, | ||
RunE: func(cmd *cobra.Command, args []string) error { | ||
err := viper.ReadInConfig() | ||
if err != nil { | ||
return fmt.Errorf("read config file: %w", err) | ||
} | ||
|
||
configData := viper.AllSettings() | ||
|
||
configJSON, err := json.MarshalIndent(configData, "", " ") | ||
if err != nil { | ||
return fmt.Errorf("marshal config: %w", err) | ||
} | ||
fmt.Println(string(configJSON)) | ||
|
||
return nil | ||
}, | ||
} |
Oops, something went wrong.