blob: 19f70ed4a9470cd23b3c572a412d92fb756a1d95 [file] [log] [blame]
Sergiusz Bazanskib13b7ff2019-08-29 20:12:24 +02001package main
2
3import (
4 "context"
5 "crypto/tls"
6 "fmt"
7 "regexp"
8 "strings"
9
10 "github.com/golang/glog"
11 "google.golang.org/grpc/codes"
12 "google.golang.org/grpc/status"
13 ldap "gopkg.in/ldap.v3"
14
15 pb "code.hackerspace.pl/hscloud/cluster/prodvider/proto"
16)
17
18var (
19 reUsername = regexp.MustCompile(`^[a-zA-Z0-9_\.]+$`)
20)
21
22func (p *prodvider) Authenticate(ctx context.Context, req *pb.AuthenticateRequest) (*pb.AuthenticateResponse, error) {
23 username := strings.TrimSpace(req.Username)
24 if username == "" || !reUsername.MatchString(username) {
25 return nil, status.Error(codes.InvalidArgument, "invalid username")
26 }
27
28 password := req.Password
29 if password == "" {
30 return &pb.AuthenticateResponse{
31 Result: pb.AuthenticateResponse_RESULT_INVALID_CREDENTIALS,
32 }, nil
33 }
34
35 tlsConfig := &tls.Config{}
36 lconn, err := ldap.DialTLS("tcp", flagLDAPServer, tlsConfig)
37 if err != nil {
38 glog.Errorf("ldap.DialTLS: %v", err)
39 return nil, status.Error(codes.Unavailable, "could not context LDAP")
40 }
Sergiusz Bazanski896926c2019-08-31 15:00:51 +020041 defer lconn.Close()
Sergiusz Bazanskib13b7ff2019-08-29 20:12:24 +020042
43 dn := fmt.Sprintf(flagLDAPBindDN, username)
44 err = lconn.Bind(dn, password)
45
46 if err != nil {
47 if ldap.IsErrorWithCode(err, ldap.LDAPResultInvalidCredentials) {
48 return &pb.AuthenticateResponse{
49 Result: pb.AuthenticateResponse_RESULT_INVALID_CREDENTIALS,
50 }, nil
51 }
52
53 glog.Errorf("ldap.Bind: %v", err)
54 return nil, status.Error(codes.Unavailable, "could not query LDAP")
55 }
56
57 groups, err := p.groupMemberships(lconn, username)
58 if err != nil {
59 return nil, err
60 }
61
62 if !groups["kubernetes-users"] && !groups["staff"] {
63 return nil, status.Error(codes.PermissionDenied, "not part of staff or kubernetes-users")
64 }
65
Serge Bazanski0754ed82020-11-27 09:42:59 +000066 err = p.kubernetesSetupUser(ctx, username)
Sergiusz Bazanskib13b7ff2019-08-29 20:12:24 +020067 if err != nil {
68 glog.Errorf("kubernetesSetupUser(%v): %v", username, err)
69 return nil, status.Error(codes.Unavailable, "could not set up objects in Kubernetes")
70 }
71
Serge Bazanskif3312ef2020-08-01 17:15:52 +020072 kubernetesKeys, err := p.kubernetesCreds(username)
Sergiusz Bazanskib13b7ff2019-08-29 20:12:24 +020073 if err != nil {
74 glog.Errorf("kubernetesCreds(%q): %v", username, err)
75 return nil, status.Error(codes.Unavailable, "could not generate k8s keys")
76 }
Serge Bazanskif3312ef2020-08-01 17:15:52 +020077
Serge Bazanski0754ed82020-11-27 09:42:59 +000078 hspkiKeys, err := p.hspkiCreds(ctx, username)
Serge Bazanskif3312ef2020-08-01 17:15:52 +020079 if err != nil {
80 glog.Errorf("hspkiCreds(%q): %v", username, err)
81 return nil, status.Error(codes.Unavailable, "could not generate hspki keys")
82 }
83
Serge Bazanski02e15982021-03-17 22:39:00 +000084 crdbWaw1Keys, err := p.crdbCreds(ctx, username, "waw1")
85 if err != nil {
86 glog.Errorf("crdbCreds(%q): %v", username, err)
87 return nil, status.Error(codes.Unavailable, "could not generate crdb keys")
88 }
89
Sergiusz Bazanskib13b7ff2019-08-29 20:12:24 +020090 return &pb.AuthenticateResponse{
91 Result: pb.AuthenticateResponse_RESULT_AUTHENTICATED,
Serge Bazanskif3312ef2020-08-01 17:15:52 +020092 KubernetesKeys: kubernetesKeys,
93 HspkiKeys: hspkiKeys,
Serge Bazanski02e15982021-03-17 22:39:00 +000094 CrdbKeys: &pb.CockroachDBKeys{
95 Clusters: []*pb.CockroachDBKeys_Cluster{crdbWaw1Keys},
96 },
Sergiusz Bazanskib13b7ff2019-08-29 20:12:24 +020097 }, nil
98}
99
100func (p *prodvider) groupMemberships(lconn *ldap.Conn, username string) (map[string]bool, error) {
101 searchRequest := ldap.NewSearchRequest(
102 flagLDAPGroupSearchBase,
103 ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, 0, 0, false,
104 fmt.Sprintf("(uniqueMember=%s)", fmt.Sprintf(flagLDAPBindDN, username)),
105 []string{"dn", "cn"},
106 nil,
107 )
108
109 sr, err := lconn.Search(searchRequest)
110 if err != nil {
111 glog.Errorf("ldap.Search: %v", err)
112 return nil, status.Error(codes.Unavailable, "could not query LDAP for group")
113 }
114
115 res := make(map[string]bool)
116 for _, entry := range sr.Entries {
117 cn := entry.GetAttributeValue("cn")
118 res[cn] = true
119 }
120
121 return res, nil
122}