Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions cmd/cloudFoundryDeploy.go
Original file line number Diff line number Diff line change
Expand Up @@ -602,6 +602,8 @@ func cfDeploy(
CfSpace: config.Space,
Username: config.Username,
Password: config.Password,
ClientID: config.ClientID,
ClientSecret: config.ClientSecret,
CfLoginOpts: strings.Fields(config.LoginParameters),
})
}
Expand Down
46 changes: 40 additions & 6 deletions cmd/cloudFoundryDeploy_generated.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

57 changes: 42 additions & 15 deletions pkg/cloudfoundry/Authentication.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ func (cf *CFUtils) LoginCheck(options LoginOptions) (bool, error) {
}

// Login logs user in to Cloud Foundry via cf cli.
// Checks if user is logged in first, if not perform 'cf login' command with appropriate parameters
// Checks if user is logged in first, if not perform 'cf login' command with appropriate parameters.
// If ClientID and ClientSecret are provided, client credentials flow is used instead:
// cf api → cf auth --client-credentials → cf target
func (cf *CFUtils) Login(options LoginOptions) error {
var err error

Expand All @@ -25,8 +27,17 @@ func (cf *CFUtils) Login(options LoginOptions) error {
_c = &command.Command{}
}

if options.CfAPIEndpoint == "" || options.CfOrg == "" || options.CfSpace == "" || options.Username == "" || options.Password == "" {
return fmt.Errorf("Failed to login to Cloud Foundry: %w", errors.New("Parameters missing. Please provide the Cloud Foundry Endpoint, Org, Space, Username and Password"))
// Decide authentication flow
useClientCredentials := options.ClientID != "" && options.ClientSecret != ""

if useClientCredentials {
if options.CfAPIEndpoint == "" || options.CfOrg == "" || options.CfSpace == "" {
return fmt.Errorf("Failed to login to Cloud Foundry: %w", errors.New("Parameters missing. Please provide the Cloud Foundry Endpoint, Org and Space for client credentials login"))
}
} else {
if options.CfAPIEndpoint == "" || options.CfOrg == "" || options.CfSpace == "" || options.Username == "" || options.Password == "" {
return fmt.Errorf("Failed to login to Cloud Foundry: %w", errors.New("Parameters missing. Please provide the Cloud Foundry Endpoint, Org, Space, Username and Password"))
}
}

var loggedIn bool
Expand All @@ -39,19 +50,31 @@ func (cf *CFUtils) Login(options LoginOptions) error {

if err == nil {
log.Entry().Info("Logging in to Cloud Foundry")

var cfLoginScript = append([]string{
"login",
"-a", options.CfAPIEndpoint,
"-o", options.CfOrg,
"-s", options.CfSpace,
"-u", options.Username,
"-p", options.Password,
}, options.CfLoginOpts...)

log.Entry().WithField("cfAPI:", options.CfAPIEndpoint).WithField("cfOrg", options.CfOrg).WithField("space", options.CfSpace).Info("Logging into Cloud Foundry..")

err = _c.RunExecutable("cf", cfLoginScript...)
if useClientCredentials {
// Step 1: set API endpoint
err = _c.RunExecutable("cf", "api", options.CfAPIEndpoint)
if err == nil {
// Step 2: authenticate with client credentials
authArgs := append([]string{"auth", options.ClientID, options.ClientSecret, "--client-credentials"}, options.CfLoginOpts...)
err = _c.RunExecutable("cf", authArgs...)
}
if err == nil {
// Step 3: target org and space
err = _c.RunExecutable("cf", "target", "-o", options.CfOrg, "-s", options.CfSpace)
}
} else {
var cfLoginScript = append([]string{
"login",
"-a", options.CfAPIEndpoint,
"-o", options.CfOrg,
"-s", options.CfSpace,
"-u", options.Username,
"-p", options.Password,
}, options.CfLoginOpts...)
err = _c.RunExecutable("cf", cfLoginScript...)
}
}

if err != nil {
Expand Down Expand Up @@ -92,7 +115,11 @@ type LoginOptions struct {
CfSpace string
Username string
Password string
CfLoginOpts []string
// ClientID and ClientSecret enable XSUAA client credentials authentication.
// When both are set, 'cf auth --client-credentials' is used instead of 'cf login'.
ClientID string
ClientSecret string
CfLoginOpts []string
}

// CFUtils ...
Expand Down
36 changes: 32 additions & 4 deletions resources/metadata/cloudFoundryDeploy.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -331,12 +331,12 @@ spec:
secret: false
- name: password
type: string
description: "Password"
description: "Password. Not required when clientId and clientSecret are provided."
scope:
- PARAMETERS
- STAGES
- STEPS
mandatory: true
mandatory: false
secret: true
resourceRef:
- name: cfCredentialsId
Expand All @@ -360,12 +360,12 @@ spec:
mandatory: true
- name: username
type: string
description: User name used for deployment
description: User name used for deployment. Not required when clientId and clientSecret are provided.
scope:
- PARAMETERS
- STAGES
- STEPS
mandatory: true
mandatory: false
secret: true
resourceRef:
- name: cfCredentialsId
Expand All @@ -374,6 +374,34 @@ spec:
- type: vaultSecret
default: cloudfoundry-$(org)-$(space)
name: cloudfoundryVaultSecretName
- name: clientId
type: string
description: "Client ID for XSUAA client credentials authentication (`cf auth --client-credentials`).
When both clientId and clientSecret are provided, username and password are not required."
scope:
- PARAMETERS
- STAGES
- STEPS
mandatory: false
secret: true
resourceRef:
- type: vaultSecret
default: cloudfoundry-$(org)-$(space)
name: cloudfoundryVaultSecretName
- name: clientSecret
type: string
description: "Client Secret for XSUAA client credentials authentication.
When both clientId and clientSecret are provided, username and password are not required."
scope:
- PARAMETERS
- STAGES
- STEPS
mandatory: false
secret: true
resourceRef:
- type: vaultSecret
default: cloudfoundry-$(org)-$(space)
name: cloudfoundryVaultSecretName
containers:
- name: cfDeploy
image: ppiper/cf-cli:latest
Expand Down
Loading