/
oauthclientregistry.go
104 lines (86 loc) · 3.43 KB
/
oauthclientregistry.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
package oauthclient
import (
"fmt"
"strconv"
"strings"
kapi "k8s.io/kubernetes/pkg/api"
kclient "k8s.io/kubernetes/pkg/client/unversioned"
"k8s.io/kubernetes/pkg/serviceaccount"
scopeauthorizer "github.com/openshift/origin/pkg/authorization/authorizer/scope"
oauthapi "github.com/openshift/origin/pkg/oauth/api"
"github.com/openshift/origin/pkg/oauth/registry/oauthclient"
)
const (
OAuthRedirectURISecretAnnotationPrefix = "serviceaccounts.openshift.io/oauth-redirecturi."
OAuthWantChallengesAnnotationPrefix = "serviceaccounts.openshift.io/oauth-want-challenges"
)
type saOAuthClientAdapter struct {
saClient kclient.ServiceAccountsNamespacer
secretClient kclient.SecretsNamespacer
delegate oauthclient.Getter
}
var _ oauthclient.Getter = &saOAuthClientAdapter{}
func NewServiceAccountOAuthClientGetter(saClient kclient.ServiceAccountsNamespacer, secretClient kclient.SecretsNamespacer, delegate oauthclient.Getter) oauthclient.Getter {
return &saOAuthClientAdapter{saClient: saClient, secretClient: secretClient, delegate: delegate}
}
func (a *saOAuthClientAdapter) GetClient(ctx kapi.Context, name string) (*oauthapi.OAuthClient, error) {
saNamespace, saName, err := serviceaccount.SplitUsername(name)
if err != nil {
return a.delegate.GetClient(ctx, name)
}
sa, err := a.saClient.ServiceAccounts(saNamespace).Get(saName)
if err != nil {
return nil, err
}
redirectURIs := []string{}
for key, value := range sa.Annotations {
if strings.HasPrefix(key, OAuthRedirectURISecretAnnotationPrefix) {
redirectURIs = append(redirectURIs, value)
}
}
if len(redirectURIs) == 0 {
return nil, fmt.Errorf("%v has no redirectURIs; set %v<some-value>=<redirect>", name, OAuthRedirectURISecretAnnotationPrefix)
}
tokens, err := a.getServiceAccountTokens(sa)
if err != nil {
return nil, err
}
if len(tokens) == 0 {
return nil, fmt.Errorf("%v has no tokens", name)
}
saWantsChallenges, _ := strconv.ParseBool(sa.Annotations[OAuthWantChallengesAnnotationPrefix])
saClient := &oauthapi.OAuthClient{
ObjectMeta: kapi.ObjectMeta{Name: name},
ScopeRestrictions: getScopeRestrictionsFor(saNamespace, saName),
AdditionalSecrets: tokens,
RespondWithChallenges: saWantsChallenges,
// TODO update this to allow https redirection to any
// 1. service IP (useless in general)
// 2. service DNS (useless in general)
// 3. route DNS (useful)
// 4. loopback? (useful, but maybe a bit weird)
RedirectURIs: redirectURIs,
}
return saClient, nil
}
func getScopeRestrictionsFor(namespace, name string) []oauthapi.ScopeRestriction {
return []oauthapi.ScopeRestriction{
{ExactValues: []string{scopeauthorizer.UserIndicator + scopeauthorizer.UserInfo, scopeauthorizer.UserIndicator + scopeauthorizer.UserAccessCheck}},
{ClusterRole: &oauthapi.ClusterRoleScopeRestriction{RoleNames: []string{"*"}, Namespaces: []string{namespace}, AllowEscalation: true}},
}
}
// getServiceAccountTokens returns all ServiceAccountToken secrets for the given ServiceAccount
func (a *saOAuthClientAdapter) getServiceAccountTokens(sa *kapi.ServiceAccount) ([]string, error) {
allSecrets, err := a.secretClient.Secrets(sa.Namespace).List(kapi.ListOptions{})
if err != nil {
return nil, err
}
tokens := []string{}
for i := range allSecrets.Items {
secret := allSecrets.Items[i]
if serviceaccount.IsServiceAccountToken(&secret, sa) {
tokens = append(tokens, string(secret.Data[kapi.ServiceAccountTokenKey]))
}
}
return tokens, nil
}