Skip to content

Commit

Permalink
Move secrets to secrets resource (#82)
Browse files Browse the repository at this point in the history
This PR moves the NATS token and
`accessToken.soure.clientCredentials.clientSecret` out from the
configMap and into secrets loaded as environment variables in the
container.

FileToken.TokenPath gets flagged by secrets scanners despite it not
being a sensitive credential, so that got renamed to just `File` which
still makes sense in the config path
`accessToken.source.file.tokenPath`.

AccessToken was also giving chart consumers trouble with security
scans

Signed-off-by: Adam Mohammed <admohammed@equinix.com>
  • Loading branch information
adammohammed authored Sep 3, 2024
1 parent fd273cb commit bc97b30
Show file tree
Hide file tree
Showing 8 changed files with 69 additions and 18 deletions.
17 changes: 16 additions & 1 deletion chart/iam-runtime-infratographer/templates/_container.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,23 @@ securityContext: {{- toYaml . | nindent 2 }}
{{- with $values.resources }}
resources: {{- toYaml . | nindent 2 }}
{{- end }}
env:
{{- with $values.secrets.nats.token }}
- name: IAMRUNTIME_EVENTS_NATS_TOKEN
valueFrom:
secretKeyRef:
key: natsToken
name: {{ include "iam-runtime-infratographer.resource.fullname" (dict "suffix" "secrets" "context" $) | quote }}
{{- end }}
{{- with $values.secrets.accessToken.source.clientSecret }}
- name: IAMRUNTIME_ACCESSTOKENPROVIDER_SOURCE_CLIENTCREDENTIALS_CLIENTSECRET
valueFrom:
secretKeyRef:
key: clientSecret
name: {{ include "iam-runtime-infratographer.resource.fullname" (dict "suffix" "secrets" "context" $) | quote }}
{{- end }}
{{- with $values.extraEnv }}
env: {{- toYaml . | nindent 2 }}
{{- toYaml . | nindent 2 }}
{{- end }}
volumeMounts:
- name: {{ include "iam-runtime-infratographer.resource.fullname" (dict "suffix" "config" "context" $) | quote }}
Expand Down
12 changes: 12 additions & 0 deletions chart/iam-runtime-infratographer/templates/_secrets.tpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{{- define "iam-runtime-infratographer.secrets" }}
{{- $values := (index .Subcharts "iam-runtime-infratographer").Values -}}
---
apiVersion: v1
kind: Secret
metadata:
name: {{ include "iam-runtime-infratographer.resource.fullname" (dict "suffix" "secrets" "context" $) | quote }}
labels: {{- include "common.labels.standard" $ | nindent 4 }}
data:
natsToken: {{ $values.secrets.nats.token | quote }}
clientSecret: {{ $values.secrets.accessToken.source.clientSecret | quote }}
{{- end }}
22 changes: 14 additions & 8 deletions chart/iam-runtime-infratographer/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,6 @@ config:
publishPrefix: ""
# -- publishTopic NATS publihs topic to use.
publishTopic: ""
# -- token NATS user token to use.
token: ""
# -- credsFile path to NATS credentials file
credsFile: ""
tracing:
Expand All @@ -37,14 +35,14 @@ config:
url: ""
# -- insecure if TLS should be disabled.
insecure: false
accessToken:
accessTokenProvider:
# -- enabled configures the access token source for GetAccessToken requests.
enabled: false
# -- (duration) expiryDelta sets early expiry validation for the token.
# @default -- 10s
expiryDelta: 0
source:
fileToken:
file:
# -- tokenPath is the path to the source jwt token.
tokenPath: ""
clientCredentials:
Expand All @@ -55,10 +53,6 @@ config:
# This attribute also supports a file path by prefixing the value with `file://`.
# example: `file:///var/secrets/client-id`
clientID: ""
# -- clientSecret is the client credentials secret which is used to retrieve a token from the issuer.
# This attribute also supports a file path by prefixing the value with `file://`.
# example: `file:///var/secrets/client-secret`
clientSecret: ""
exchange:
# -- issuer specifies the URL for the issuer for the exchanged token.
# The Issuer must support OpenID discovery to discover the token endpoint.
Expand All @@ -70,6 +64,18 @@ config:
# @default -- urn:ietf:params:oauth:token-type:jwt
tokenType: ""

secrets:
nats:
# -- token NATS user token to use.
token: ""
accessToken:
source:
# -- clientSecret is the client credentials secret which is used to retrieve a token from the issuer.
# This attribute also supports a file path by prefixing the value with `file://`.
# example: `file:///var/secrets/client-secret`
clientSecret: ""


# -- restartPolicy set to Always if using with initContainers on kube 1.29 and up
# with the SideContainer feature flag enabled.
# ref: https://kubernetes.io/docs/concepts/workloads/pods/sidecar-containers/#sidecar-containers-and-pod-lifecycle
Expand Down
1 change: 1 addition & 0 deletions cmd/serve.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ func init() {
permissions.AddFlags(cmdFlags)
eventsx.AddFlags(cmdFlags)
server.AddFlags(cmdFlags)
accesstoken.AddFlags(cmdFlags)

if err := viper.BindPFlags(cmdFlags); err != nil {
panic(err)
Expand Down
4 changes: 2 additions & 2 deletions config.example.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ events:
publishTopic: myapp
tracing:
enabled: false
accessToken:
accessTokenProvider:
enabled: false
source:
fileToken:
file:
tokenPath: /var/run/secrets/kubernetes.io/serviceaccount/token
# clientCredentials:
# issuer: https://identity-api.enterprise.dev/
Expand Down
25 changes: 21 additions & 4 deletions internal/accesstoken/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@ package accesstoken

import (
"errors"
"flag"
"fmt"
"net/url"
"time"

"github.com/spf13/pflag"
"go.infratographer.com/iam-runtime-infratographer/internal/filetokensource"
"go.uber.org/multierr"
)
Expand Down Expand Up @@ -69,8 +71,8 @@ func (c Config) Validate() error {
// AccessTokenSourceConfig configures the source token location for access token exchanges.
// Only one source may be configured at a time.
type AccessTokenSourceConfig struct {
// FileToken specifies the configuration for sourcing tokens from a file.
FileToken filetokensource.Config
// File specifies the configuration for sourcing tokens from a file.
File filetokensource.Config

// ClientCredentials specifies the oauth2 credentials source the token from.
ClientCredentials ClientCredentialConfig
Expand All @@ -80,10 +82,10 @@ type AccessTokenSourceConfig struct {
func (c AccessTokenSourceConfig) Validate() error {
var configured int

if c.FileToken.Configured() {
if c.File.Configured() {
configured++

if err := c.FileToken.Validate(); err != nil {
if err := c.File.Validate(); err != nil {
return fmt.Errorf("fileToken: %w", err)
}
}
Expand Down Expand Up @@ -166,3 +168,18 @@ func (c ClientCredentialConfig) Validate() error {

return nil
}

func AddFlags(flags *pflag.FlagSet) {
flags.Bool("accessTokenProvider.enabled", false, "enabled configures the access token source for GetAccessToken requests")

flags.String("accessTokenProvider.source.file.tokenpath", "", "tokenPath is the path to the source jwt token")
flags.String("accessTokenProvider.source.clientCredentials.issuer", "", "issuer specifies the URL for the issuer for the token request. The Issuer must support OpenID discovery to discover the token endpoint.")
flags.String("accessTokenProvider.source.clientCredentials.clientID", "", "clientID is the client credentials id which is used to retrieve a token from the issuer. This attribute also supports a file path by prefixing the value with `file://`. example: `file:///var/secrets/client-id`")
flags.String("accessTokenProvider.source.clientCredentials.clientSecret", "", "clientSecret is the client credentials secret which is used to retrieve a token from the issuer. This attribute also supports a file path by prefixing the value with `file://`. example: `file:///var/secrets/client-secret`")

flag.String("accessTokenProvider.exchange.issuer", "", "issuer specifies the URL for the issuer for the exchanged token. The Issuer must support OpenID discovery to discover the token endpoint")
flag.String("accessTokenProvider.exchange.grantType", "urn:ietf:params:oauth:grant-type:token-exchange", "grantType configures the grant type")
flag.String("accessTokenProvider.exchange.tokenType", "", "tokenType configures the token type")

flag.Duration("accessTokenProvider.expiryDelta", 10*time.Second, "sets the early expiry validation for the token")
}
4 changes: 2 additions & 2 deletions internal/accesstoken/tokensource.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ func (c AccessTokenSourceConfig) toTokenSource(ctx context.Context) (oauth2.Toke
return nil, err
}

if c.FileToken.Configured() {
tokensource, err := c.FileToken.ToTokenSource()
if c.File.Configured() {
tokensource, err := c.File.ToTokenSource()
if err != nil {
return nil, fmt.Errorf("file token: %w", err)
}
Expand Down
2 changes: 1 addition & 1 deletion internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,5 @@ type Config struct {
Events eventsx.Config
Server server.Config
Tracing otelx.Config
AccessToken accesstoken.Config
AccessToken accesstoken.Config `mapstructure:"accessTokenProvider"`
}

0 comments on commit bc97b30

Please sign in to comment.