Skip to content

Commit 0f50e9f

Browse files
committed
WIP: Proof of concept / demo
Signed-off-by: Richard Wall <[email protected]>
1 parent a361867 commit 0f50e9f

File tree

10 files changed

+344
-63
lines changed

10 files changed

+344
-63
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,5 @@ predicate.json
1414
*.tgz
1515

1616
_bin
17+
.envrc
18+
.env

agent.yaml

Lines changed: 54 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,55 @@
1-
server: "https://platform.jetstack.io"
2-
organization_id: "my-organization"
3-
cluster_id: "my_cluster"
4-
period: "0h1m0s"
1+
machineHub:
2+
subdomain: tlskp-test
3+
credentialsSecretName: machinehub-credentials
54
data-gatherers:
6-
- kind: "dummy"
7-
name: "dummy"
8-
config:
9-
failed-attempts: 5
10-
- kind: "dummy"
11-
name: "dummy-fail"
12-
config:
13-
always-fail: true
14-
venafi-cloud:
15-
uploader_id: "example-id"
16-
upload_path: "/example/endpoint/path"
17-
5+
# gather k8s apiserver version information
6+
- kind: "k8s-discovery"
7+
name: "k8s-discovery"
8+
- kind: "k8s-dynamic"
9+
name: "k8s/serviceaccounts"
10+
config:
11+
resource-type:
12+
resource: serviceaccounts
13+
version: v1
14+
- kind: "k8s-dynamic"
15+
name: "k8s/secrets"
16+
config:
17+
resource-type:
18+
version: v1
19+
resource: secrets
20+
field-selectors:
21+
- type!=kubernetes.io/service-account-token
22+
- type!=kubernetes.io/dockercfg
23+
- type!=kubernetes.io/dockerconfigjson
24+
- type!=kubernetes.io/basic-auth
25+
- type!=kubernetes.io/ssh-auth
26+
- type!=bootstrap.kubernetes.io/token
27+
- type!=helm.sh/release.v1
28+
- kind: "k8s-dynamic"
29+
name: "k8s/roles"
30+
config:
31+
resource-type:
32+
version: v1
33+
group: rbac.authorization.k8s.io
34+
resource: roles
35+
- kind: "k8s-dynamic"
36+
name: "k8s/clusterroles"
37+
config:
38+
resource-type:
39+
version: v1
40+
group: rbac.authorization.k8s.io
41+
resource: clusterroles
42+
- kind: "k8s-dynamic"
43+
name: "k8s/rolebindings"
44+
config:
45+
resource-type:
46+
version: v1
47+
group: rbac.authorization.k8s.io
48+
resource: rolebindings
49+
- kind: "k8s-dynamic"
50+
name: "k8s/clusterrolebindings"
51+
config:
52+
resource-type:
53+
version: v1
54+
group: rbac.authorization.k8s.io
55+
resource: clusterrolebindings

deploy/charts/venafi-kubernetes-agent/templates/deployment.yaml

Lines changed: 22 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,26 @@ spec:
4949
valueFrom:
5050
fieldRef:
5151
fieldPath: spec.nodeName
52+
- name: ARK_USERNAME
53+
valueFrom:
54+
secretKeyRef:
55+
name: {{ .Values.authentication.secretName }}
56+
key: ARK_USERNAME
57+
- name: ARK_SECRET
58+
valueFrom:
59+
secretKeyRef:
60+
name: {{ .Values.authentication.secretName }}
61+
key: ARK_SECRET
62+
- name: ARK_PLATFORM_DOMAIN
63+
valueFrom:
64+
secretKeyRef:
65+
name: {{ .Values.authentication.secretName }}
66+
key: ARK_PLATFORM_DOMAIN
67+
- name: ARK_SUBDOMAIN
68+
valueFrom:
69+
secretKeyRef:
70+
name: {{ .Values.authentication.secretName }}
71+
key: ARK_SUBDOMAIN
5272
{{- with .Values.http_proxy }}
5373
- name: HTTP_PROXY
5474
value: {{ . }}
@@ -71,18 +91,8 @@ spec:
7191
- "agent"
7292
- "-c"
7393
- "/etc/venafi/agent/config/{{ default "config.yaml" .Values.config.configmap.key }}"
74-
{{- if .Values.authentication.venafiConnection.enabled }}
75-
- --venafi-connection
76-
- {{ .Values.authentication.venafiConnection.name | quote }}
77-
- --venafi-connection-namespace
78-
- {{ .Values.authentication.venafiConnection.namespace | quote }}
79-
{{- else }}
80-
- "--client-id"
81-
- {{ .Values.config.clientId | quote }}
82-
- "--private-key-path"
83-
- "/etc/venafi/agent/key/{{ .Values.authentication.secretKey }}"
84-
{{- end }}
85-
- --venafi-cloud
94+
- --log-level=6
95+
- --machine-hub
8696
{{- if .Values.metrics.enabled }}
8797
- --enable-metrics
8898
{{- end }}
@@ -95,11 +105,6 @@ spec:
95105
- name: config
96106
mountPath: "/etc/venafi/agent/config"
97107
readOnly: true
98-
{{- if not .Values.authentication.venafiConnection.enabled }}
99-
- name: credentials
100-
mountPath: "/etc/venafi/agent/key"
101-
readOnly: true
102-
{{- end }}
103108
{{- with .Values.volumeMounts }}
104109
{{- toYaml . | nindent 12 }}
105110
{{- end }}
@@ -137,12 +142,6 @@ spec:
137142
configMap:
138143
name: {{ default "agent-config" .Values.config.configmap.name }}
139144
optional: false
140-
{{- if not .Values.authentication.venafiConnection.enabled }}
141-
- name: credentials
142-
secret:
143-
secretName: {{ .Values.authentication.secretName }}
144-
optional: false
145-
{{- end }}
146145
{{- with .Values.volumes }}
147146
{{- toYaml . | nindent 8 }}
148147
{{- end }}

hack/e2e/ca/config.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
machineHub:
2+
subdomain: tlskp-test
3+
credentialsSecretName: todo-unused

hack/e2e/ca/test.sh

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
#!/usr/bin/env bash
2+
#
3+
set -o nounset
4+
set -o errexit
5+
set -o pipefail
6+
7+
# CyberArk API configuration
8+
: ${ARK_USERNAME?}
9+
: ${ARK_SECRET?}
10+
: ${ARK_PLATFORM_DOMAIN?}
11+
: ${ARK_SUBDOMAIN?}
12+
13+
# The base URL of the OCI registry used for Docker images and Helm charts
14+
# E.g. ttl.sh/6ee49a01-c8ba-493e-bae9-4d8567574b56
15+
: ${OCI_BASE?}
16+
17+
k8s_namespace=cyberark
18+
19+
script_dir=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &>/dev/null && pwd)
20+
root_dir=$(cd "${script_dir}/../../.." && pwd)
21+
export TERM=dumb
22+
23+
tmp_dir="$(mktemp -d /tmp/jetstack-secure.XXXXX)"
24+
25+
pushd "${tmp_dir}"
26+
> release.env
27+
make -C "$root_dir" release \
28+
OCI_SIGN_ON_PUSH=false \
29+
oci_platforms=linux/amd64 \
30+
oci_preflight_image_name=$OCI_BASE/images/venafi-agent \
31+
helm_chart_image_name=$OCI_BASE/charts/venafi-kubernetes-agent \
32+
GITHUB_OUTPUT="${tmp_dir}/release.env"
33+
source release.env
34+
35+
kind create cluster || true
36+
kubectl create ns "$k8s_namespace" || true
37+
38+
kubectl create secret generic agent-credentials \
39+
--namespace "$k8s_namespace" \
40+
--from-literal=ARK_USERNAME=$ARK_USERNAME \
41+
--from-literal=ARK_SECRET=$ARK_SECRET \
42+
--from-literal=ARK_PLATFORM_DOMAIN=$ARK_PLATFORM_DOMAIN \
43+
--from-literal=ARK_SUBDOMAIN=$ARK_SUBDOMAIN
44+
45+
helm upgrade agent "oci://${OCI_BASE}/charts/venafi-kubernetes-agent" \
46+
--install \
47+
--create-namespace \
48+
--namespace "$k8s_namespace" \
49+
--version "${RELEASE_HELM_CHART_VERSION}" \
50+
--set fullnameOverride=agent \
51+
--set "image.repository=${OCI_BASE}/images/venafi-agent" \
52+
--values "${script_dir}/values.agent.yaml"
53+
54+
kubectl scale -n "$k8s_namespace" deployment agent --replicas=0
55+
kubectl get cm -n "$k8s_namespace" agent-config -o jsonpath={.data.config\\.yaml} > config.original.yaml
56+
yq eval-all '. as $item ireduce ({}; . * $item)' config.original.yaml "${script_dir}/config.yaml" > config.yaml
57+
kubectl delete cm -n "$k8s_namespace" agent-config
58+
kubectl create cm -n "$k8s_namespace" agent-config --from-file=config.yaml
59+
kubectl scale -n "$k8s_namespace" deployment agent --replicas=1

hack/e2e/ca/values.agent.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# Empty

pkg/agent/config.go

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -606,12 +606,12 @@ func ValidateAndCombineConfig(log logr.Logger, cfg Config, flags AgentCmdFlags)
606606
res.ClusterID = clusterID
607607
res.ClusterDescription = cfg.ClusterDescription
608608

609-
// Validation of `data-gatherers`.
610-
if dgErr := ValidateDataGatherers(cfg.DataGatherers); dgErr != nil {
611-
errs = multierror.Append(errs, dgErr)
612-
}
613-
res.DataGatherers = cfg.DataGatherers
614609
}
610+
// Validation of `data-gatherers`.
611+
if dgErr := ValidateDataGatherers(cfg.DataGatherers); dgErr != nil {
612+
errs = multierror.Append(errs, dgErr)
613+
}
614+
res.DataGatherers = cfg.DataGatherers
615615

616616
// Validation of --period, -p, and the `period` field, as well as
617617
// --backoff-max-time, --one-shot, and --strict. The flag --period/-p takes
@@ -702,7 +702,6 @@ func ValidateAndCombineConfig(log logr.Logger, cfg Config, flags AgentCmdFlags)
702702
if err != nil {
703703
return CombinedConfig{}, nil, multierror.Prefix(err, "validating creds:")
704704
}
705-
706705
return res, preflightClient, nil
707706
}
708707

pkg/agent/run.go

Lines changed: 57 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@ import (
3535
"github.com/jetstack/preflight/pkg/clusteruid"
3636
"github.com/jetstack/preflight/pkg/datagatherer"
3737
"github.com/jetstack/preflight/pkg/datagatherer/k8s"
38+
"github.com/jetstack/preflight/pkg/internal/cyberark/dataupload"
39+
"github.com/jetstack/preflight/pkg/internal/cyberark/identity"
40+
"github.com/jetstack/preflight/pkg/internal/cyberark/servicediscovery"
3841
"github.com/jetstack/preflight/pkg/kubeconfig"
3942
"github.com/jetstack/preflight/pkg/logs"
4043
"github.com/jetstack/preflight/pkg/version"
@@ -79,6 +82,44 @@ func Run(cmd *cobra.Command, args []string) (returnErr error) {
7982
return fmt.Errorf("While evaluating configuration: %v", err)
8083
}
8184

85+
var caClient *dataupload.CyberArkClient
86+
{
87+
platformDomain := os.Getenv("ARK_PLATFORM_DOMAIN")
88+
subdomain := os.Getenv("ARK_SUBDOMAIN")
89+
username := os.Getenv("ARK_USERNAME")
90+
password := []byte(os.Getenv("ARK_SECRET"))
91+
92+
const (
93+
discoveryContextServiceName = "inventory"
94+
separator = "."
95+
)
96+
97+
// TODO(wallrj): Maybe get this URL via the service discovery API.
98+
// https://platform-discovery.integration-cyberark.cloud/api/public/tenant-discovery?allEndpoints=true&bySubdomain=tlskp-test
99+
serviceURL := fmt.Sprintf("https://%s%s%s.%s", subdomain, separator, discoveryContextServiceName, platformDomain)
100+
101+
var (
102+
identityClient *identity.Client
103+
err error
104+
)
105+
if platformDomain == "cyberark.cloud" {
106+
identityClient, err = identity.New(ctx, subdomain)
107+
} else {
108+
discoveryClient := servicediscovery.New(servicediscovery.WithIntegrationEndpoint())
109+
identityClient, err = identity.NewWithDiscoveryClient(ctx, discoveryClient, subdomain)
110+
}
111+
if err != nil {
112+
return fmt.Errorf("while creating the CyberArk identity client: %v", err)
113+
}
114+
if err := identityClient.LoginUsernamePassword(ctx, username, password); err != nil {
115+
return fmt.Errorf("while logging in: %v", err)
116+
}
117+
caClient, err = dataupload.NewCyberArkClient(nil, serviceURL, identityClient.AuthenticateRequest)
118+
if err != nil {
119+
return fmt.Errorf("while creating the CyberArk dataupload client: %v", err)
120+
}
121+
}
122+
82123
// We need the cluster UID before we progress further so it can be sent along with other data readings
83124

84125
{
@@ -185,7 +226,6 @@ func Run(cmd *cobra.Command, args []string) (returnErr error) {
185226
}
186227

187228
dataGatherers := map[string]datagatherer.DataGatherer{}
188-
189229
// load datagatherer config and boot each one
190230
for _, dgConfig := range config.DataGatherers {
191231
kind := dgConfig.Kind
@@ -262,7 +302,7 @@ func Run(cmd *cobra.Command, args []string) (returnErr error) {
262302
// be cancelled, which will cause this blocking loop to exit
263303
// instead of waiting for the time period.
264304
for {
265-
if err := gatherAndOutputData(klog.NewContext(ctx, log), eventf, config, preflightClient, dataGatherers); err != nil {
305+
if err := gatherAndOutputData(klog.NewContext(ctx, log), eventf, config, preflightClient, caClient, dataGatherers); err != nil {
266306
return err
267307
}
268308

@@ -316,7 +356,7 @@ func newEventf(log logr.Logger, installNS string) (Eventf, error) {
316356
// Like Printf but for sending events to the agent's Pod object.
317357
type Eventf func(eventType, reason, msg string, args ...interface{})
318358

319-
func gatherAndOutputData(ctx context.Context, eventf Eventf, config CombinedConfig, preflightClient client.Client, dataGatherers map[string]datagatherer.DataGatherer) error {
359+
func gatherAndOutputData(ctx context.Context, eventf Eventf, config CombinedConfig, preflightClient client.Client, caClient *dataupload.CyberArkClient, dataGatherers map[string]datagatherer.DataGatherer) error {
320360
log := klog.FromContext(ctx).WithName("gatherAndOutputData")
321361
var readings []*api.DataReading
322362

@@ -338,8 +378,18 @@ func gatherAndOutputData(ctx context.Context, eventf Eventf, config CombinedConf
338378
}
339379
}
340380

381+
clusterID := clusteruid.ClusterUIDFromContext(ctx)
382+
payload := api.DataReadingsPost{
383+
AgentMetadata: &api.AgentMetadata{
384+
Version: version.PreflightVersion,
385+
ClusterID: clusterID,
386+
},
387+
DataGatherTime: time.Now(),
388+
DataReadings: readings,
389+
}
341390
if config.OutputPath != "" {
342-
data, err := json.MarshalIndent(readings, "", " ")
391+
392+
data, err := json.MarshalIndent(payload, "", " ")
343393
if err != nil {
344394
return fmt.Errorf("failed to marshal JSON: %s", err)
345395
}
@@ -359,11 +409,11 @@ func gatherAndOutputData(ctx context.Context, eventf Eventf, config CombinedConf
359409
eventf("Warning", "PushingErr", "retrying in %v after error: %s", t, err)
360410
log.Info("Warning: PushingErr: retrying", "in", t, "reason", err)
361411
})
362-
363412
if config.MachineHubMode {
364413
post := func() (any, error) {
365-
log.Info("machine hub mode not yet implemented")
366-
return struct{}{}, nil
414+
return struct{}{}, caClient.PostDataReadingsWithOptions(ctx, payload, dataupload.Options{
415+
ClusterName: clusterID,
416+
})
367417
}
368418

369419
group.Go(func() error {

0 commit comments

Comments
 (0)