// handleAuth checks authentication against etcd using CanConnect and sets the needed // environment variables for later parts of the builder to use. It takes in the SSH // connection metadata, the public key of the user, and returns the SSH // permissions of the connection and an error if they are not authorized. func handleAuth(conn ssh.ConnMetadata, key ssh.PublicKey) (*ssh.Permissions, error) { if conn.User() != "git" { return nil, ErrUnauthorized } keydata := string(bytes.TrimSpace(ssh.MarshalAuthorizedKey(key))) etcd := etcd.NewClient([]string{*etcduplink}) fp := utils.GetFingerprint(keydata) user, allowed := utils.CanConnect(etcd, keydata) if allowed { log.Printf("User %s (%s) accepted with fingerprint %s", user, conn.RemoteAddr().String(), fp) return &ssh.Permissions{ Extensions: map[string]string{ "environ": fmt.Sprintf("USER=%s\nKEY='%s'\nFINGERPRINT=%s\n", user, keydata, fp), "user": user, "fingerprint": fp, }, }, nil } else { log.Printf("Connection from %s rejected (bad key)", conn.RemoteAddr().String()) } return nil, ErrUnauthorized }
func register(w http.ResponseWriter, req *http.Request) { if req.Method != "POST" { utils.Reply(r, w, "Invalid method", http.StatusMethodNotAllowed) return } err := req.ParseForm() if err != nil { utils.Reply(r, w, "Could not parse form "+err.Error(), http.StatusInternalServerError) return } password := utils.HashPassword([]byte(req.Form.Get("password")), []byte("lagann")) key := req.Form.Get("sshkey") uname := req.Form.Get("username") fp := utils.GetFingerprint(key) if fp == "error" { utils.Reply(r, w, "Invalid SSH key", 401) return } if _, err := client.Get(constants.ETCD_LAGANN_USERS+uname, false, false); err == nil { utils.Reply(r, w, "User "+uname+" already exists", 409) } else { client.Set(constants.ETCD_BUILDER_USERS+uname+"/"+fp, key, 0) client.Set(constants.ETCD_LAGANN_USERS+uname+"/password", base64.StdEncoding.EncodeToString(password), 0) authkey := uuid.New() client.Set(constants.ETCD_LAGANN_AUTHKEYS+authkey, uname, 0) utils.Reply(r, w, "User "+uname+" created.", 200, map[string]interface{}{ "authkey": authkey, "user": uname, }) } }