Skip to content

Commit

Permalink
feat(svc-account): Enables tokenURL. Removes tenantID
Browse files Browse the repository at this point in the history
Enables the  use of tokenURL for VCP service account authentication. The tenantID attribute has been removed.
  • Loading branch information
rvelaVenafi committed Apr 4, 2024
1 parent 39eb64f commit d81a22d
Show file tree
Hide file tree
Showing 18 changed files with 225 additions and 123 deletions.
4 changes: 2 additions & 2 deletions cmd/vcert/args.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ var (

type commandFlags struct {
apiKey string
vaasTenantID string
externalJWT string
idPJWT string
tokenURL string
appInfo string
audience string
caDN string
Expand Down
4 changes: 2 additions & 2 deletions cmd/vcert/commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -874,11 +874,11 @@ func getVaaSCredentials(vaasConnector *cloud.Connector, cfg *vcert.Config) error
fmt.Println("api_key_expires: ", apiKey.ValidityEndDateString)
}
// Request access token
} else if cfg.Credentials.ExternalIdPJWT != "" && cfg.Credentials.TenantID != "" {
} else if cfg.Credentials.IdPJWT != "" && cfg.Credentials.IdentityProvider != nil && cfg.Credentials.IdentityProvider.TokenURL != "" {
// Request access token from VaaS service account
tokenResponse, err := vaasConnector.GetAccessToken(cfg.Credentials)
if err != nil {
return fmt.Errorf("failed to request access token from VaaS: %w", err)
return fmt.Errorf("failed to request access token from VCP: %w", err)
}

if flags.credFormat == "json" {
Expand Down
14 changes: 8 additions & 6 deletions cmd/vcert/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -161,12 +161,14 @@ func buildConfigVaaS(flags *commandFlags) (*vcert.Config, error) {
ConnectorType: endpoint.ConnectorTypeCloud,
BaseUrl: flags.url,
Credentials: &endpoint.Authentication{
User: flags.email,
Password: flags.password,
AccessToken: flags.token,
APIKey: flags.apiKey,
TenantID: flags.vaasTenantID,
ExternalIdPJWT: flags.externalJWT,
User: flags.email,
Password: flags.password,
AccessToken: flags.token,
APIKey: flags.apiKey,
IdPJWT: flags.idPJWT,
IdentityProvider: &endpoint.OAuthProvider{
TokenURL: flags.tokenURL,
},
},
}, nil
}
Expand Down
25 changes: 17 additions & 8 deletions cmd/vcert/datareader.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,15 @@ func readData(commandName string) error {
fileName := flags.distinguishedName[5:]
bytes, err := os.ReadFile(fileName)
if err != nil {
return fmt.Errorf("Failed to read Certificate DN: %s", err)
return fmt.Errorf("failed to read Certificate DN: %s", err)
}
flags.distinguishedName = strings.TrimSpace(string(bytes))
}
if strings.HasPrefix(flags.keyPassword, filePrefix) {
fileName := flags.keyPassword[5:]
bytes, err := os.ReadFile(fileName)
if err != nil {
return fmt.Errorf("Failed to read password from file: %s", err)
return fmt.Errorf("failed to read password from file: %s", err)
}
flags.keyPassword = strings.TrimSpace(string(bytes))
}
Expand All @@ -46,21 +46,30 @@ func readData(commandName string) error {
certFileName := flags.thumbprint[5:]
flags.thumbprint, err = readThumbprintFromFile(certFileName)
if err != nil {
return fmt.Errorf("Failed to read certificate fingerprint: %s", err)
return fmt.Errorf("failed to read certificate fingerprint: %s", err)
}
}

if strings.HasPrefix(flags.externalJWT, filePrefix) {
fileName := flags.externalJWT[5:]
if strings.HasPrefix(flags.idPJWT, filePrefix) {
fileName := flags.idPJWT[5:]
bytes, err := os.ReadFile(fileName)
if err != nil {
return fmt.Errorf("failed to read external JWT from file: %w", err)
return fmt.Errorf("failed to read IdP JWT from file: %w", err)
}
flags.externalJWT = strings.TrimSpace(string(bytes))
flags.idPJWT = strings.TrimSpace(string(bytes))
}

if strings.HasPrefix(flags.tokenURL, filePrefix) {
fileName := flags.tokenURL[5:]
bytes, err := os.ReadFile(fileName)
if err != nil {
return fmt.Errorf("failed to read token URL from file: %w", err)
}
flags.tokenURL = strings.TrimSpace(string(bytes))
}

if err = readPasswordsFromInputFlags(commandName, &flags); err != nil {
return fmt.Errorf("Failed to read password from input: %s", err)
return fmt.Errorf("failed to read password from input: %s", err)
}
return nil
}
14 changes: 7 additions & 7 deletions cmd/vcert/envVars.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ const (
vCertZone = "VCERT_ZONE"
vCertToken = "VCERT_TOKEN" // #nosec G101
vCertApiKey = "VCERT_APIKEY" // #nosec G101
vCertTenantID = "VCERT_TENANT_ID"
vCertExternalJWT = "VCERT_EXTERNAL_JWT"
vCertIdPJWT = "VCERT_IDP_JWT"
vCertTokenURL = "VCERT_TOKEN_URL"
vCertTrustBundle = "VCERT_TRUST_BUNDLE"
vcertUser = "VCERT_USER"
vcertPassword = "VCERT_PASSWORD"
Expand Down Expand Up @@ -52,13 +52,13 @@ var (
FlagName: "-k",
},
{
EnvVarName: vCertTenantID,
Destination: &flags.vaasTenantID,
FlagName: "--tenant-id",
EnvVarName: vCertTokenURL,
Destination: &flags.tokenURL,
FlagName: "--token-url",
},
{
EnvVarName: vCertExternalJWT,
Destination: &flags.externalJWT,
EnvVarName: vCertIdPJWT,
Destination: &flags.idPJWT,
FlagName: "--external-jwt",
},
{
Expand Down
25 changes: 13 additions & 12 deletions cmd/vcert/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,13 @@ var (
Aliases: []string{"u"},
}

flagTokenUrl = &cli.StringFlag{
Name: "token-url",
Usage: "REQUIRED/VCP. The URL of the token service." +
"\n\t\tExample: --token-url https://api.venafi.cloud/v1/oauth2/v2.0/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee/token",
Destination: &flags.tokenURL,
}

flagUrlDeprecated = &cli.StringFlag{
Name: "venafi-saas-url",
Usage: "",
Expand All @@ -57,16 +64,10 @@ var (
Aliases: []string{"k"},
}

flagTenantID = &cli.StringFlag{
Name: "tenant-id",
Usage: "REQUIRED/VaaS. The ID of your tenant/company in VaaS. Use it along --external-jwt to retrieve an access token for VaaS",
Destination: &flags.vaasTenantID,
}

flagExternalJWT = &cli.StringFlag{
Name: "external-jwt",
Usage: "REQUIRED/VaaS. The JWT of the Identity Provider associated to the service account to be used. Use it along --tenant-id flag to retrieve an access token for VaaS",
Destination: &flags.externalJWT,
flagIdPJWT = &cli.StringFlag{
Name: "idp-jwt",
Usage: "REQUIRED/VCP. The JWT of the Identity Provider associated to the service account to be used. Use it along --token-url flag to retrieve an access token for VCP",
Destination: &flags.idPJWT,
}

flagDeviceURL = &cli.StringFlag{
Expand Down Expand Up @@ -864,8 +865,8 @@ var (
flagAudience,
flagDeviceURL,
commonFlags,
flagTenantID,
flagExternalJWT,
flagTokenUrl,
flagIdPJWT,
))

checkCredFlags = sortedFlags(flagsApppend(
Expand Down
4 changes: 2 additions & 2 deletions cmd/vcert/validators.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,8 +103,8 @@ func validateConnectionFlags(commandName string) error {
flags.password != "" ||
flags.token != "" ||
flags.url != "" ||
flags.vaasTenantID != "" ||
flags.externalJWT != "" ||
flags.tokenURL != "" ||
flags.idPJWT != "" ||
flags.testMode {
return fmt.Errorf("connection details cannot be specified with flags when --config is used")
}
Expand Down
18 changes: 7 additions & 11 deletions cmd/vcert/validatorsCloud.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,18 @@ func validateConnectionFlagsCloud(commandName string) error {

//getcred command
if commandName == commandGetCredName {
tenantIDPresent := flags.vaasTenantID != "" || getPropertyFromEnvironment(vCertTenantID) != ""
externalJWTPresent := flags.externalJWT != "" || getPropertyFromEnvironment(vCertExternalJWT) != ""
svcAccountPresent := tenantIDPresent && externalJWTPresent
tokenURLPresent := flags.tokenURL != "" || getPropertyFromEnvironment(vCertTokenURL) != ""
jwtPresent := flags.idPJWT != "" || getPropertyFromEnvironment(vCertIdPJWT) != ""
svcAccountPresent := tokenURLPresent && jwtPresent
emailPresent := flags.email != ""

if tenantIDPresent && !externalJWTPresent {
return fmt.Errorf("missing jwt for service account authentication. Set the jwt using --external-jwt flag")
if tokenURLPresent && !jwtPresent {
return fmt.Errorf("missing jwt for service account authentication. Set the jwt using --idp-jwt flag")
}

advice := "Use --tenant-id/--external-jwt for authentication or --email for registration"
advice := "Use --token-url/--idp-jwt for authentication or --email for registration"
if !svcAccountPresent && !emailPresent {
return fmt.Errorf("missing flags for Venafi as a Service authentication. %s", advice)
return fmt.Errorf("missing flags for Venafi Cloud Platform authentication. %s", advice)
}

return nil
Expand All @@ -38,9 +38,5 @@ func validateConnectionFlagsCloud(commandName string) error {
return fmt.Errorf("missing flags for Venafi as a Service authentication. %s", advice)
}

if apiKeyPresent && tokenPresent {
return fmt.Errorf("multiple methods set for Venafi as a Service authentication. %s", advice)
}

return nil
}
28 changes: 15 additions & 13 deletions examples/tlspc-svc-account/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@ import (
)

const (
TlspcUrl = "TLSPC_URL"
TlspcZone = "TLSPC_ZONE"
TlspcTenantId = "TLSPC_TENANT_ID"
TlspcJwt = "TLSPC_JWT"
vcpURL = "VCP_URL"
vcpZone = "VCP_ZONE"
vcpTokenURL = "VCP_TOKEN_URL"
vcpJWT = "VCP_JWT"

envVarNotSet = "environment variable not set: %s"

Expand All @@ -27,19 +27,19 @@ const (
func main() {

// URL can be nil if using production TLSPC
url := os.Getenv(TlspcUrl)
url := os.Getenv(vcpURL)

zone, found := os.LookupEnv(TlspcZone)
zone, found := os.LookupEnv(vcpZone)
if !found {
log.Fatalf(envVarNotSet, TlspcZone)
log.Fatalf(envVarNotSet, vcpZone)
}
tenantID, found := os.LookupEnv(TlspcTenantId)
tokenURL, found := os.LookupEnv(vcpTokenURL)
if !found {
log.Fatalf(envVarNotSet, TlspcTenantId)
log.Fatalf(envVarNotSet, vcpTokenURL)
}
jwt, found := os.LookupEnv(TlspcJwt)
jwt, found := os.LookupEnv(vcpJWT)
if !found {
log.Fatalf(envVarNotSet, TlspcJwt)
log.Fatalf(envVarNotSet, vcpJWT)
}

userAgent := fmt.Sprintf("%s/%s %s", name, version, util.DefaultUserAgent)
Expand All @@ -48,8 +48,10 @@ func main() {
BaseUrl: url,
Zone: zone,
Credentials: &endpoint.Authentication{
TenantID: tenantID,
ExternalIdPJWT: jwt,
IdPJWT: jwt,
IdentityProvider: &endpoint.OAuthProvider{
TokenURL: tokenURL,
},
},
UserAgent: &userAgent,
}
Expand Down
16 changes: 8 additions & 8 deletions pkg/endpoint/authentication.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,22 +19,21 @@ package endpoint
// Authentication provides a struct for authentication data. Either specify User and Password for Trust Protection Platform
// or Firefly or ClientId and ClientSecret for Firefly or specify an APIKey for TLS Protect Cloud.
type Authentication struct {
//TPP Auth methods
// User and password
// TPP Auth methods
// user and password
User string `yaml:"user,omitempty"` //**DEPRECATED** Use access/refresh token or client certificate instead
Password string `yaml:"password,omitempty"` //**DEPRECATED** Use access/refresh token or client certificate instead
// Tokens
// tokens
AccessToken string `yaml:"accessToken,omitempty"`
RefreshToken string `yaml:"refreshToken,omitempty"`
// Client certificate
// client certificate
ClientPKCS12 bool `yaml:"-"`

//TLSPC Auth methods
// VCP Auth methods
// API key
APIKey string `yaml:"apiKey,omitempty"`
// Service account
TenantID string `yaml:"tenantId,omitempty"`
ExternalIdPJWT string `yaml:"externalJWT,omitempty"`
IdPJWT string `yaml:"idPJWT,omitempty"`

// IDP Auth method
ClientId string `yaml:"clientId,omitempty"`
Expand All @@ -46,7 +45,8 @@ type Authentication struct {

// OAuthProvider provides a struct for the OAuth 2.0 providers information
type OAuthProvider struct {
// OIDC Auth methods
DeviceURL string `yaml:"-"`
TokenURL string `yaml:"tokenURL,omitempty"`
TokenURL string `yaml:"tokenURL,omitempty"` // This attribute is also used by VCP service account
Audience string `yaml:"audience,omitempty"`
}
Loading

0 comments on commit d81a22d

Please sign in to comment.