Skip to content

Commit 56d79f9

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

File tree

13 files changed

+357
-69
lines changed

13 files changed

+357
-69
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

api/datareading.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@ type DataReading struct {
2828
type GatheredResource struct {
2929
// Resource is a reference to a k8s object that was found by the informer
3030
// should be of type unstructured.Unstructured, raw Object
31-
Resource interface{}
32-
DeletedAt Time
31+
Resource interface{} `json: "resource"`
32+
DeletedAt Time `json:"deleted_at,omitempty"`
3333
}
3434

3535
func (v GatheredResource) MarshalJSON() ([]byte, error) {

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: 56 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ 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/identity"
39+
"github.com/jetstack/preflight/pkg/internal/cyberark/servicediscovery"
3840
"github.com/jetstack/preflight/pkg/kubeconfig"
3941
"github.com/jetstack/preflight/pkg/logs"
4042
"github.com/jetstack/preflight/pkg/version"
@@ -79,6 +81,44 @@ func Run(cmd *cobra.Command, args []string) (returnErr error) {
7981
return fmt.Errorf("While evaluating configuration: %v", err)
8082
}
8183

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

84124
{
@@ -185,7 +225,6 @@ func Run(cmd *cobra.Command, args []string) (returnErr error) {
185225
}
186226

187227
dataGatherers := map[string]datagatherer.DataGatherer{}
188-
189228
// load datagatherer config and boot each one
190229
for _, dgConfig := range config.DataGatherers {
191230
kind := dgConfig.Kind
@@ -262,7 +301,7 @@ func Run(cmd *cobra.Command, args []string) (returnErr error) {
262301
// be cancelled, which will cause this blocking loop to exit
263302
// instead of waiting for the time period.
264303
for {
265-
if err := gatherAndOutputData(klog.NewContext(ctx, log), eventf, config, preflightClient, dataGatherers); err != nil {
304+
if err := gatherAndOutputData(klog.NewContext(ctx, log), eventf, config, preflightClient, caClient, dataGatherers); err != nil {
266305
return err
267306
}
268307

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

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

@@ -338,8 +377,18 @@ func gatherAndOutputData(ctx context.Context, eventf Eventf, config CombinedConf
338377
}
339378
}
340379

380+
clusterID := clusteruid.ClusterUIDFromContext(ctx)
381+
payload := api.DataReadingsPost{
382+
AgentMetadata: &api.AgentMetadata{
383+
Version: version.PreflightVersion,
384+
ClusterID: clusterID,
385+
},
386+
DataGatherTime: time.Now(),
387+
DataReadings: readings,
388+
}
341389
if config.OutputPath != "" {
342-
data, err := json.MarshalIndent(readings, "", " ")
390+
391+
data, err := json.MarshalIndent(payload, "", " ")
343392
if err != nil {
344393
return fmt.Errorf("failed to marshal JSON: %s", err)
345394
}
@@ -359,11 +408,11 @@ func gatherAndOutputData(ctx context.Context, eventf Eventf, config CombinedConf
359408
eventf("Warning", "PushingErr", "retrying in %v after error: %s", t, err)
360409
log.Info("Warning: PushingErr: retrying", "in", t, "reason", err)
361410
})
362-
363411
if config.MachineHubMode {
364412
post := func() (any, error) {
365-
log.Info("machine hub mode not yet implemented")
366-
return struct{}{}, nil
413+
return struct{}{}, caClient.PostDataReadingsWithOptions(ctx, payload, client.CyberArkClientOptions{
414+
ClusterName: clusterID,
415+
})
367416
}
368417

369418
group.Go(func() error {

pkg/client/client_cyberark.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,6 @@ import (
55
)
66

77
type CyberArkClient = dataupload.CyberArkClient
8+
type CyberArkClientOptions = dataupload.Options
89

910
var NewCyberArkClient = dataupload.NewCyberArkClient

0 commit comments

Comments
 (0)