forked from hswaw/hscloud
Serge Bazanski
97b5cd7b58
This is a mega-change, but attempting to split this up further is probably not worth the effort. Summary: 1. Bump up bazel, rules_go, and others. 2. Switch to new go target naming (bye bye go_default_library) 3. Move go deps to go.mod/go.sum, use make gazelle generate from that 4. Bump up Python deps a bit And also whatever was required to actually get things to work - loads of small useless changes. Tested to work on NixOS and Ubuntu 20.04: $ bazel build //... $ bazel test //... Change-Id: I8364bdaa1406b9ae4d0385a6b607f3e7989f98a9 Reviewed-on: https://gerrit.hackerspace.pl/c/hscloud/+/1583 Reviewed-by: q3k <q3k@hackerspace.pl>
122 lines
3.3 KiB
Go
122 lines
3.3 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"crypto/tls"
|
|
"fmt"
|
|
"regexp"
|
|
"strings"
|
|
|
|
ldap "github.com/go-ldap/ldap/v3"
|
|
"github.com/golang/glog"
|
|
"google.golang.org/grpc/codes"
|
|
"google.golang.org/grpc/status"
|
|
|
|
pb "code.hackerspace.pl/hscloud/cluster/prodvider/proto"
|
|
)
|
|
|
|
var (
|
|
reUsername = regexp.MustCompile(`^[a-zA-Z0-9_\.]+$`)
|
|
)
|
|
|
|
func (p *prodvider) Authenticate(ctx context.Context, req *pb.AuthenticateRequest) (*pb.AuthenticateResponse, error) {
|
|
username := strings.TrimSpace(req.Username)
|
|
if username == "" || !reUsername.MatchString(username) {
|
|
return nil, status.Error(codes.InvalidArgument, "invalid username")
|
|
}
|
|
|
|
password := req.Password
|
|
if password == "" {
|
|
return &pb.AuthenticateResponse{
|
|
Result: pb.AuthenticateResponse_RESULT_INVALID_CREDENTIALS,
|
|
}, nil
|
|
}
|
|
|
|
tlsConfig := &tls.Config{}
|
|
lconn, err := ldap.DialTLS("tcp", flagLDAPServer, tlsConfig)
|
|
if err != nil {
|
|
glog.Errorf("ldap.DialTLS: %v", err)
|
|
return nil, status.Error(codes.Unavailable, "could not context LDAP")
|
|
}
|
|
defer lconn.Close()
|
|
|
|
dn := fmt.Sprintf(flagLDAPBindDN, username)
|
|
err = lconn.Bind(dn, password)
|
|
|
|
if err != nil {
|
|
if ldap.IsErrorWithCode(err, ldap.LDAPResultInvalidCredentials) {
|
|
return &pb.AuthenticateResponse{
|
|
Result: pb.AuthenticateResponse_RESULT_INVALID_CREDENTIALS,
|
|
}, nil
|
|
}
|
|
|
|
glog.Errorf("ldap.Bind: %v", err)
|
|
return nil, status.Error(codes.Unavailable, "could not query LDAP")
|
|
}
|
|
|
|
groups, err := p.groupMemberships(lconn, username)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if !groups["kubernetes-users"] && !groups["staff"] {
|
|
return nil, status.Error(codes.PermissionDenied, "not part of staff or kubernetes-users")
|
|
}
|
|
|
|
err = p.kubernetesSetupUser(ctx, username)
|
|
if err != nil {
|
|
glog.Errorf("kubernetesSetupUser(%v): %v", username, err)
|
|
return nil, status.Error(codes.Unavailable, "could not set up objects in Kubernetes")
|
|
}
|
|
|
|
kubernetesKeys, err := p.kubernetesCreds(username)
|
|
if err != nil {
|
|
glog.Errorf("kubernetesCreds(%q): %v", username, err)
|
|
return nil, status.Error(codes.Unavailable, "could not generate k8s keys")
|
|
}
|
|
|
|
hspkiKeys, err := p.hspkiCreds(ctx, username)
|
|
if err != nil {
|
|
glog.Errorf("hspkiCreds(%q): %v", username, err)
|
|
return nil, status.Error(codes.Unavailable, "could not generate hspki keys")
|
|
}
|
|
|
|
crdbWaw1Keys, err := p.crdbCreds(ctx, username, "waw1")
|
|
if err != nil {
|
|
glog.Errorf("crdbCreds(%q): %v", username, err)
|
|
return nil, status.Error(codes.Unavailable, "could not generate crdb keys")
|
|
}
|
|
|
|
return &pb.AuthenticateResponse{
|
|
Result: pb.AuthenticateResponse_RESULT_AUTHENTICATED,
|
|
KubernetesKeys: kubernetesKeys,
|
|
HspkiKeys: hspkiKeys,
|
|
CrdbKeys: &pb.CockroachDBKeys{
|
|
Clusters: []*pb.CockroachDBKeys_Cluster{crdbWaw1Keys},
|
|
},
|
|
}, nil
|
|
}
|
|
|
|
func (p *prodvider) groupMemberships(lconn *ldap.Conn, username string) (map[string]bool, error) {
|
|
searchRequest := ldap.NewSearchRequest(
|
|
flagLDAPGroupSearchBase,
|
|
ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, 0, 0, false,
|
|
fmt.Sprintf("(uniqueMember=%s)", fmt.Sprintf(flagLDAPBindDN, username)),
|
|
[]string{"dn", "cn"},
|
|
nil,
|
|
)
|
|
|
|
sr, err := lconn.Search(searchRequest)
|
|
if err != nil {
|
|
glog.Errorf("ldap.Search: %v", err)
|
|
return nil, status.Error(codes.Unavailable, "could not query LDAP for group")
|
|
}
|
|
|
|
res := make(map[string]bool)
|
|
for _, entry := range sr.Entries {
|
|
cn := entry.GetAttributeValue("cn")
|
|
res[cn] = true
|
|
}
|
|
|
|
return res, nil
|
|
}
|