Add client_cert_token_timeout to address GH-9465 (#10528)
This commit is contained in:
parent
96b753f3b0
commit
273a720440
|
@ -23,6 +23,7 @@ type FlatConfig struct {
|
||||||
ClientID *string `mapstructure:"client_id" cty:"client_id" hcl:"client_id"`
|
ClientID *string `mapstructure:"client_id" cty:"client_id" hcl:"client_id"`
|
||||||
ClientSecret *string `mapstructure:"client_secret" cty:"client_secret" hcl:"client_secret"`
|
ClientSecret *string `mapstructure:"client_secret" cty:"client_secret" hcl:"client_secret"`
|
||||||
ClientCertPath *string `mapstructure:"client_cert_path" cty:"client_cert_path" hcl:"client_cert_path"`
|
ClientCertPath *string `mapstructure:"client_cert_path" cty:"client_cert_path" hcl:"client_cert_path"`
|
||||||
|
ClientCertExpireTimeout *string `mapstructure:"client_cert_token_timeout" required:"false" cty:"client_cert_token_timeout" hcl:"client_cert_token_timeout"`
|
||||||
ClientJWT *string `mapstructure:"client_jwt" cty:"client_jwt" hcl:"client_jwt"`
|
ClientJWT *string `mapstructure:"client_jwt" cty:"client_jwt" hcl:"client_jwt"`
|
||||||
ObjectID *string `mapstructure:"object_id" cty:"object_id" hcl:"object_id"`
|
ObjectID *string `mapstructure:"object_id" cty:"object_id" hcl:"object_id"`
|
||||||
TenantID *string `mapstructure:"tenant_id" required:"false" cty:"tenant_id" hcl:"tenant_id"`
|
TenantID *string `mapstructure:"tenant_id" required:"false" cty:"tenant_id" hcl:"tenant_id"`
|
||||||
|
@ -151,6 +152,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
||||||
"client_id": &hcldec.AttrSpec{Name: "client_id", Type: cty.String, Required: false},
|
"client_id": &hcldec.AttrSpec{Name: "client_id", Type: cty.String, Required: false},
|
||||||
"client_secret": &hcldec.AttrSpec{Name: "client_secret", Type: cty.String, Required: false},
|
"client_secret": &hcldec.AttrSpec{Name: "client_secret", Type: cty.String, Required: false},
|
||||||
"client_cert_path": &hcldec.AttrSpec{Name: "client_cert_path", Type: cty.String, Required: false},
|
"client_cert_path": &hcldec.AttrSpec{Name: "client_cert_path", Type: cty.String, Required: false},
|
||||||
|
"client_cert_token_timeout": &hcldec.AttrSpec{Name: "client_cert_token_timeout", Type: cty.String, Required: false},
|
||||||
"client_jwt": &hcldec.AttrSpec{Name: "client_jwt", Type: cty.String, Required: false},
|
"client_jwt": &hcldec.AttrSpec{Name: "client_jwt", Type: cty.String, Required: false},
|
||||||
"object_id": &hcldec.AttrSpec{Name: "object_id", Type: cty.String, Required: false},
|
"object_id": &hcldec.AttrSpec{Name: "object_id", Type: cty.String, Required: false},
|
||||||
"tenant_id": &hcldec.AttrSpec{Name: "tenant_id", Type: cty.String, Required: false},
|
"tenant_id": &hcldec.AttrSpec{Name: "tenant_id", Type: cty.String, Required: false},
|
||||||
|
|
|
@ -22,6 +22,7 @@ type FlatConfig struct {
|
||||||
ClientID *string `mapstructure:"client_id" cty:"client_id" hcl:"client_id"`
|
ClientID *string `mapstructure:"client_id" cty:"client_id" hcl:"client_id"`
|
||||||
ClientSecret *string `mapstructure:"client_secret" cty:"client_secret" hcl:"client_secret"`
|
ClientSecret *string `mapstructure:"client_secret" cty:"client_secret" hcl:"client_secret"`
|
||||||
ClientCertPath *string `mapstructure:"client_cert_path" cty:"client_cert_path" hcl:"client_cert_path"`
|
ClientCertPath *string `mapstructure:"client_cert_path" cty:"client_cert_path" hcl:"client_cert_path"`
|
||||||
|
ClientCertExpireTimeout *string `mapstructure:"client_cert_token_timeout" required:"false" cty:"client_cert_token_timeout" hcl:"client_cert_token_timeout"`
|
||||||
ClientJWT *string `mapstructure:"client_jwt" cty:"client_jwt" hcl:"client_jwt"`
|
ClientJWT *string `mapstructure:"client_jwt" cty:"client_jwt" hcl:"client_jwt"`
|
||||||
ObjectID *string `mapstructure:"object_id" cty:"object_id" hcl:"object_id"`
|
ObjectID *string `mapstructure:"object_id" cty:"object_id" hcl:"object_id"`
|
||||||
TenantID *string `mapstructure:"tenant_id" required:"false" cty:"tenant_id" hcl:"tenant_id"`
|
TenantID *string `mapstructure:"tenant_id" required:"false" cty:"tenant_id" hcl:"tenant_id"`
|
||||||
|
@ -76,6 +77,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
||||||
"client_id": &hcldec.AttrSpec{Name: "client_id", Type: cty.String, Required: false},
|
"client_id": &hcldec.AttrSpec{Name: "client_id", Type: cty.String, Required: false},
|
||||||
"client_secret": &hcldec.AttrSpec{Name: "client_secret", Type: cty.String, Required: false},
|
"client_secret": &hcldec.AttrSpec{Name: "client_secret", Type: cty.String, Required: false},
|
||||||
"client_cert_path": &hcldec.AttrSpec{Name: "client_cert_path", Type: cty.String, Required: false},
|
"client_cert_path": &hcldec.AttrSpec{Name: "client_cert_path", Type: cty.String, Required: false},
|
||||||
|
"client_cert_token_timeout": &hcldec.AttrSpec{Name: "client_cert_token_timeout", Type: cty.String, Required: false},
|
||||||
"client_jwt": &hcldec.AttrSpec{Name: "client_jwt", Type: cty.String, Required: false},
|
"client_jwt": &hcldec.AttrSpec{Name: "client_jwt", Type: cty.String, Required: false},
|
||||||
"object_id": &hcldec.AttrSpec{Name: "object_id", Type: cty.String, Required: false},
|
"object_id": &hcldec.AttrSpec{Name: "object_id", Type: cty.String, Required: false},
|
||||||
"tenant_id": &hcldec.AttrSpec{Name: "tenant_id", Type: cty.String, Required: false},
|
"tenant_id": &hcldec.AttrSpec{Name: "tenant_id", Type: cty.String, Required: false},
|
||||||
|
|
|
@ -39,6 +39,8 @@ type Config struct {
|
||||||
// The path to a pem-encoded certificate that will be used to authenticate
|
// The path to a pem-encoded certificate that will be used to authenticate
|
||||||
// as the specified AAD SP.
|
// as the specified AAD SP.
|
||||||
ClientCertPath string `mapstructure:"client_cert_path"`
|
ClientCertPath string `mapstructure:"client_cert_path"`
|
||||||
|
// The timeout for the JWT Token when using a [client certificate](#client_cert_path). Defaults to 1 hour.
|
||||||
|
ClientCertExpireTimeout time.Duration `mapstructure:"client_cert_token_timeout" required:"false"`
|
||||||
// A JWT bearer token for client auth (RFC 7523, Sec. 2.2) that will be used
|
// A JWT bearer token for client auth (RFC 7523, Sec. 2.2) that will be used
|
||||||
// to authenticate the AAD SP. Provides more control over token the expiration
|
// to authenticate the AAD SP. Provides more control over token the expiration
|
||||||
// when using certificate authentication than when using `client_cert_path`.
|
// when using certificate authentication than when using `client_cert_path`.
|
||||||
|
@ -163,6 +165,9 @@ func (c Config) Validate(errs *packersdk.MultiError) {
|
||||||
if _, err := os.Stat(c.ClientCertPath); err != nil {
|
if _, err := os.Stat(c.ClientCertPath); err != nil {
|
||||||
errs = packersdk.MultiErrorAppend(errs, fmt.Errorf("client_cert_path is not an accessible file: %v", err))
|
errs = packersdk.MultiErrorAppend(errs, fmt.Errorf("client_cert_path is not an accessible file: %v", err))
|
||||||
}
|
}
|
||||||
|
if c.ClientCertExpireTimeout < 5*time.Minute {
|
||||||
|
errs = packersdk.MultiErrorAppend(errs, fmt.Errorf("client_cert_token_timeout will expire within 5 minutes, please set a value greater than 5 minutes"))
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -259,7 +264,7 @@ func (c Config) GetServicePrincipalToken(
|
||||||
auth = NewSecretOAuthTokenProvider(*c.cloudEnvironment, c.ClientID, c.ClientSecret, c.TenantID)
|
auth = NewSecretOAuthTokenProvider(*c.cloudEnvironment, c.ClientID, c.ClientSecret, c.TenantID)
|
||||||
case authTypeClientCert:
|
case authTypeClientCert:
|
||||||
say("Getting tokens using client certificate")
|
say("Getting tokens using client certificate")
|
||||||
auth, err = NewCertOAuthTokenProvider(*c.cloudEnvironment, c.ClientID, c.ClientCertPath, c.TenantID)
|
auth, err = NewCertOAuthTokenProvider(*c.cloudEnvironment, c.ClientID, c.ClientCertPath, c.TenantID, c.ClientCertExpireTimeout)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -336,6 +341,10 @@ func (c *Config) FillParameters() error {
|
||||||
c.TenantID = tenantID
|
c.TenantID = tenantID
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if c.ClientCertExpireTimeout == 0 {
|
||||||
|
c.ClientCertExpireTimeout = time.Hour
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -95,6 +95,16 @@ func Test_ClientConfig_RequiredParametersSet(t *testing.T) {
|
||||||
},
|
},
|
||||||
wantErr: true,
|
wantErr: true,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "client_cert_token_timeout should be 5 minutes or more",
|
||||||
|
config: Config{
|
||||||
|
SubscriptionID: "ok",
|
||||||
|
ClientID: "ok",
|
||||||
|
ClientCertPath: "/dev/null",
|
||||||
|
ClientCertExpireTimeout: 1 * time.Minute,
|
||||||
|
},
|
||||||
|
wantErr: true,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "too many client_* values",
|
name: "too many client_* values",
|
||||||
config: Config{
|
config: Config{
|
||||||
|
|
|
@ -18,14 +18,14 @@ import (
|
||||||
"github.com/hashicorp/packer/builder/azure/pkcs12"
|
"github.com/hashicorp/packer/builder/azure/pkcs12"
|
||||||
)
|
)
|
||||||
|
|
||||||
func NewCertOAuthTokenProvider(env azure.Environment, clientID, clientCertPath, tenantID string) (oAuthTokenProvider, error) {
|
func NewCertOAuthTokenProvider(env azure.Environment, clientID, clientCertPath, tenantID string, certExpireTimeout time.Duration) (oAuthTokenProvider, error) {
|
||||||
cert, key, err := readCert(clientCertPath)
|
cert, key, err := readCert(clientCertPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("Error reading certificate: %v", err)
|
return nil, fmt.Errorf("Error reading certificate: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
audience := fmt.Sprintf("%s%s/oauth2/token", env.ActiveDirectoryEndpoint, tenantID)
|
audience := fmt.Sprintf("%s%s/oauth2/token", env.ActiveDirectoryEndpoint, tenantID)
|
||||||
jwt, err := makeJWT(clientID, audience, cert, key, time.Hour, true)
|
jwt, err := makeJWT(clientID, audience, cert, key, certExpireTimeout, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("Error generating JWT: %v", err)
|
return nil, fmt.Errorf("Error generating JWT: %v", err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,6 +49,7 @@ type FlatConfig struct {
|
||||||
ClientID *string `mapstructure:"client_id" cty:"client_id" hcl:"client_id"`
|
ClientID *string `mapstructure:"client_id" cty:"client_id" hcl:"client_id"`
|
||||||
ClientSecret *string `mapstructure:"client_secret" cty:"client_secret" hcl:"client_secret"`
|
ClientSecret *string `mapstructure:"client_secret" cty:"client_secret" hcl:"client_secret"`
|
||||||
ClientCertPath *string `mapstructure:"client_cert_path" cty:"client_cert_path" hcl:"client_cert_path"`
|
ClientCertPath *string `mapstructure:"client_cert_path" cty:"client_cert_path" hcl:"client_cert_path"`
|
||||||
|
ClientCertExpireTimeout *string `mapstructure:"client_cert_token_timeout" required:"false" cty:"client_cert_token_timeout" hcl:"client_cert_token_timeout"`
|
||||||
ClientJWT *string `mapstructure:"client_jwt" cty:"client_jwt" hcl:"client_jwt"`
|
ClientJWT *string `mapstructure:"client_jwt" cty:"client_jwt" hcl:"client_jwt"`
|
||||||
ObjectID *string `mapstructure:"object_id" cty:"object_id" hcl:"object_id"`
|
ObjectID *string `mapstructure:"object_id" cty:"object_id" hcl:"object_id"`
|
||||||
TenantID *string `mapstructure:"tenant_id" required:"false" cty:"tenant_id" hcl:"tenant_id"`
|
TenantID *string `mapstructure:"tenant_id" required:"false" cty:"tenant_id" hcl:"tenant_id"`
|
||||||
|
@ -163,6 +164,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
||||||
"client_id": &hcldec.AttrSpec{Name: "client_id", Type: cty.String, Required: false},
|
"client_id": &hcldec.AttrSpec{Name: "client_id", Type: cty.String, Required: false},
|
||||||
"client_secret": &hcldec.AttrSpec{Name: "client_secret", Type: cty.String, Required: false},
|
"client_secret": &hcldec.AttrSpec{Name: "client_secret", Type: cty.String, Required: false},
|
||||||
"client_cert_path": &hcldec.AttrSpec{Name: "client_cert_path", Type: cty.String, Required: false},
|
"client_cert_path": &hcldec.AttrSpec{Name: "client_cert_path", Type: cty.String, Required: false},
|
||||||
|
"client_cert_token_timeout": &hcldec.AttrSpec{Name: "client_cert_token_timeout", Type: cty.String, Required: false},
|
||||||
"client_jwt": &hcldec.AttrSpec{Name: "client_jwt", Type: cty.String, Required: false},
|
"client_jwt": &hcldec.AttrSpec{Name: "client_jwt", Type: cty.String, Required: false},
|
||||||
"object_id": &hcldec.AttrSpec{Name: "object_id", Type: cty.String, Required: false},
|
"object_id": &hcldec.AttrSpec{Name: "object_id", Type: cty.String, Required: false},
|
||||||
"tenant_id": &hcldec.AttrSpec{Name: "tenant_id", Type: cty.String, Required: false},
|
"tenant_id": &hcldec.AttrSpec{Name: "tenant_id", Type: cty.String, Required: false},
|
||||||
|
|
|
@ -49,6 +49,7 @@ type FlatConfig struct {
|
||||||
ClientID *string `mapstructure:"client_id" cty:"client_id" hcl:"client_id"`
|
ClientID *string `mapstructure:"client_id" cty:"client_id" hcl:"client_id"`
|
||||||
ClientSecret *string `mapstructure:"client_secret" cty:"client_secret" hcl:"client_secret"`
|
ClientSecret *string `mapstructure:"client_secret" cty:"client_secret" hcl:"client_secret"`
|
||||||
ClientCertPath *string `mapstructure:"client_cert_path" cty:"client_cert_path" hcl:"client_cert_path"`
|
ClientCertPath *string `mapstructure:"client_cert_path" cty:"client_cert_path" hcl:"client_cert_path"`
|
||||||
|
ClientCertExpireTimeout *string `mapstructure:"client_cert_token_timeout" required:"false" cty:"client_cert_token_timeout" hcl:"client_cert_token_timeout"`
|
||||||
ClientJWT *string `mapstructure:"client_jwt" cty:"client_jwt" hcl:"client_jwt"`
|
ClientJWT *string `mapstructure:"client_jwt" cty:"client_jwt" hcl:"client_jwt"`
|
||||||
ObjectID *string `mapstructure:"object_id" cty:"object_id" hcl:"object_id"`
|
ObjectID *string `mapstructure:"object_id" cty:"object_id" hcl:"object_id"`
|
||||||
TenantID *string `mapstructure:"tenant_id" required:"false" cty:"tenant_id" hcl:"tenant_id"`
|
TenantID *string `mapstructure:"tenant_id" required:"false" cty:"tenant_id" hcl:"tenant_id"`
|
||||||
|
@ -87,6 +88,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
||||||
"client_id": &hcldec.AttrSpec{Name: "client_id", Type: cty.String, Required: false},
|
"client_id": &hcldec.AttrSpec{Name: "client_id", Type: cty.String, Required: false},
|
||||||
"client_secret": &hcldec.AttrSpec{Name: "client_secret", Type: cty.String, Required: false},
|
"client_secret": &hcldec.AttrSpec{Name: "client_secret", Type: cty.String, Required: false},
|
||||||
"client_cert_path": &hcldec.AttrSpec{Name: "client_cert_path", Type: cty.String, Required: false},
|
"client_cert_path": &hcldec.AttrSpec{Name: "client_cert_path", Type: cty.String, Required: false},
|
||||||
|
"client_cert_token_timeout": &hcldec.AttrSpec{Name: "client_cert_token_timeout", Type: cty.String, Required: false},
|
||||||
"client_jwt": &hcldec.AttrSpec{Name: "client_jwt", Type: cty.String, Required: false},
|
"client_jwt": &hcldec.AttrSpec{Name: "client_jwt", Type: cty.String, Required: false},
|
||||||
"object_id": &hcldec.AttrSpec{Name: "object_id", Type: cty.String, Required: false},
|
"object_id": &hcldec.AttrSpec{Name: "object_id", Type: cty.String, Required: false},
|
||||||
"tenant_id": &hcldec.AttrSpec{Name: "tenant_id", Type: cty.String, Required: false},
|
"tenant_id": &hcldec.AttrSpec{Name: "tenant_id", Type: cty.String, Required: false},
|
||||||
|
|
|
@ -61,6 +61,9 @@ you should specify `subscription_id`, `client_id` and one of `client_secret`,
|
||||||
- `client_cert_path` (string) - The location of a PEM file containing a
|
- `client_cert_path` (string) - The location of a PEM file containing a
|
||||||
certificate and private key for service principal.
|
certificate and private key for service principal.
|
||||||
|
|
||||||
|
- `client_cert_token_timeout` (duration string | ex: "1h30m12s") - How long to set the expire time on the token created when using
|
||||||
|
`client_cert_path`.
|
||||||
|
|
||||||
- `client_jwt` (string) - The bearer JWT assertion signed using a certificate
|
- `client_jwt` (string) - The bearer JWT assertion signed using a certificate
|
||||||
associated with your service principal principal. See [Azure Active
|
associated with your service principal principal. See [Azure Active
|
||||||
Directory docs](https://docs.microsoft.com/en-us/azure/active-directory/develop/active-directory-certificate-credentials)
|
Directory docs](https://docs.microsoft.com/en-us/azure/active-directory/develop/active-directory-certificate-credentials)
|
||||||
|
|
|
@ -94,6 +94,8 @@ way to authenticate the SP to AAD:
|
||||||
for the AAD SP.
|
for the AAD SP.
|
||||||
- `client_cert_path` - allows usage of a certificate to be used to
|
- `client_cert_path` - allows usage of a certificate to be used to
|
||||||
authenticate as the specified AAD SP.
|
authenticate as the specified AAD SP.
|
||||||
|
- `client_cert_token_timeout` - How long to set the expire time on the token created when using
|
||||||
|
`client_cert_path`.
|
||||||
- `client_jwt` - For advanced scenario's where the used cannot provide Packer
|
- `client_jwt` - For advanced scenario's where the used cannot provide Packer
|
||||||
the full certificate, they can provide a JWT bearer token for client auth
|
the full certificate, they can provide a JWT bearer token for client auth
|
||||||
(RFC 7523, Sec. 2.2). These bearer tokens are created and signed using a
|
(RFC 7523, Sec. 2.2). These bearer tokens are created and signed using a
|
||||||
|
|
|
@ -12,6 +12,8 @@
|
||||||
- `client_cert_path` (string) - The path to a pem-encoded certificate that will be used to authenticate
|
- `client_cert_path` (string) - The path to a pem-encoded certificate that will be used to authenticate
|
||||||
as the specified AAD SP.
|
as the specified AAD SP.
|
||||||
|
|
||||||
|
- `client_cert_token_timeout` (duration string | ex: "1h5m2s") - The timeout for the JWT Token when using a [client certificate](#client_cert_path). Defaults to 1 hour.
|
||||||
|
|
||||||
- `client_jwt` (string) - A JWT bearer token for client auth (RFC 7523, Sec. 2.2) that will be used
|
- `client_jwt` (string) - A JWT bearer token for client auth (RFC 7523, Sec. 2.2) that will be used
|
||||||
to authenticate the AAD SP. Provides more control over token the expiration
|
to authenticate the AAD SP. Provides more control over token the expiration
|
||||||
when using certificate authentication than when using `client_cert_path`.
|
when using certificate authentication than when using `client_cert_path`.
|
||||||
|
|
Loading…
Reference in New Issue