Skip to content

Commit 0b007e9

Browse files
authored
Be able to use secrets for credentials. (#87)
Support "secret:abc" for credentials. Also, rather than give the agent full cluster-reader role, this creates a cluster role and assigns it to the agent which ends up only giving the agent what it needs and no more.
1 parent 821e6a8 commit 0b007e9

File tree

3 files changed

+78
-3
lines changed

3 files changed

+78
-3
lines changed

Makefile

+3-2
Original file line numberDiff line numberDiff line change
@@ -41,13 +41,14 @@ docker-examples:
4141

4242
openshift-deploy: openshift-undeploy
4343
@echo Deploying Components to OpenShift
44-
oc adm policy add-cluster-role-to-user cluster-reader system:serviceaccount:openshift-infra:hawkular-openshift-agent
4544
oc create -f deploy/openshift/hawkular-openshift-agent-configmap.yaml -n openshift-infra
4645
oc process -f deploy/openshift/hawkular-openshift-agent.yaml | oc create -n openshift-infra -f -
46+
oc adm policy add-cluster-role-to-user hawkular-openshift-agent system:serviceaccount:openshift-infra:hawkular-openshift-agent
4747

4848
openshift-undeploy:
4949
@echo Undeploying the Agent from OpenShift
50-
oc delete all,secrets,sa,templates,configmaps,daemonsets --selector=metrics-infra=agent -n openshift-infra
50+
oc delete all,secrets,sa,templates,configmaps,daemonsets,clusterroles --selector=metrics-infra=agent -n openshift-infra
51+
oc delete clusterroles hawkular-openshift-agent
5152

5253
install:
5354
@echo Installing...

deploy/openshift/hawkular-openshift-agent.yaml

+25
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,31 @@ parameters:
1010
name: IMAGE_VERSION
1111
value: dev
1212
objects:
13+
- apiVersion: v1
14+
kind: ClusterRole
15+
metadata:
16+
name: hawkular-openshift-agent
17+
labels:
18+
metrics-infra: agent
19+
rules:
20+
- apiGroups:
21+
- ""
22+
resources:
23+
- configmaps
24+
- namespaces
25+
- nodes
26+
- pods
27+
- projects
28+
verbs:
29+
- get
30+
- list
31+
- watch
32+
- apiGroups:
33+
- ""
34+
resources:
35+
- secrets
36+
verbs:
37+
- get
1338
- apiVersion: v1
1439
kind: ServiceAccount
1540
metadata:

k8s/node_event_consumer.go

+50-1
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import (
2727
"github.com/hawkular/hawkular-openshift-agent/collector"
2828
"github.com/hawkular/hawkular-openshift-agent/collector/manager"
2929
"github.com/hawkular/hawkular-openshift-agent/config"
30+
"github.com/hawkular/hawkular-openshift-agent/config/security"
3031
"github.com/hawkular/hawkular-openshift-agent/log"
3132
"github.com/hawkular/hawkular-openshift-agent/util/expand"
3233
)
@@ -200,13 +201,19 @@ func (nec *NodeEventConsumer) startCollecting(ne *NodeEvent) {
200201
endpointTenant = os.Expand(nec.Config.Kubernetes.Tenant, mappingFunc)
201202
}
202203

204+
endpointCredentials, err := nec.determineCredentials(ne.Pod, cmeEndpoint.Credentials)
205+
if err != nil {
206+
glog.Warningf("Will not start collecting for endpoint in pod [%v] - cannot determine credentials. err=%v", ne.Pod.GetIdentifier(), err)
207+
continue
208+
}
209+
203210
// We need to convert the k8s endpoint to the generic endpoint struct.
204211
newEndpoint := &collector.Endpoint{
205212
URL: url.String(),
206213
Type: cmeEndpoint.Type,
207214
Enabled: cmeEndpoint.Enabled,
208215
Tenant: endpointTenant,
209-
Credentials: cmeEndpoint.Credentials,
216+
Credentials: endpointCredentials,
210217
Collection_Interval_Secs: cmeEndpoint.Collection_Interval_Secs,
211218
Metrics: cmeEndpoint.Metrics,
212219
Tags: cmeEndpoint.Tags,
@@ -253,6 +260,48 @@ func (nec *NodeEventConsumer) stopCollecting(ne *NodeEvent) {
253260
}
254261
}
255262

263+
// determineCredentials will build a Credentials object that contains the credentials needed to
264+
// communicate with the endpoint.
265+
func (nec *NodeEventConsumer) determineCredentials(p *Pod, cmeCredentials security.Credentials) (creds security.Credentials, err error) {
266+
// function that will extract a credential string based on its value.
267+
// If the string is prefixed with "secret:" it is assumed to be a key/value from a k8s secret.
268+
// If the string is not prefixed, it is used as-is.
269+
f := func(v string) string {
270+
if strings.HasPrefix(v, "secret:") {
271+
v = strings.TrimLeft(v, "secret:")
272+
pair := strings.SplitN(v, "/", 2)
273+
if len(pair) != 2 {
274+
err = fmt.Errorf("Secret credentials are invalid for pod [%v]", p.GetIdentifier())
275+
return ""
276+
}
277+
secret, e := nec.Discovery.Client.Secrets(p.Namespace.Name).Get(pair[0])
278+
if e != nil {
279+
err = fmt.Errorf("There is no secret named [%v] - credentials are invalid for pod [%v]. err=%v",
280+
pair[0], p.GetIdentifier(), e)
281+
return ""
282+
}
283+
secretValue, ok := secret.Data[pair[1]]
284+
if !ok {
285+
err = fmt.Errorf("There is no key named [%v] in secret named [%v] - credentials are invalid for pod [%v]",
286+
pair[1], pair[0], p.GetIdentifier())
287+
return ""
288+
}
289+
log.Debugf("Credentials obtained from secret [%v/%v] for pod [%v]", pair[0], pair[1], p.GetIdentifier())
290+
return string(secretValue)
291+
} else {
292+
return v
293+
}
294+
}
295+
296+
creds = security.Credentials{
297+
Username: f(cmeCredentials.Username),
298+
Password: f(cmeCredentials.Password),
299+
Token: f(cmeCredentials.Token),
300+
}
301+
302+
return
303+
}
304+
256305
func getIdForEndpoint(p *Pod, e K8SEndpoint) (id string, err error) {
257306
url, err := e.GetUrl(p.PodIP)
258307
if err != nil {

0 commit comments

Comments
 (0)