github.com/freiheit-com/kuberpult@v1.24.2-0.20240328135542-315d5630abe6/services/cd-service/pkg/repository/credentials.go (about)

     1  /*This file is part of kuberpult.
     2  
     3  Kuberpult is free software: you can redistribute it and/or modify
     4  it under the terms of the Expat(MIT) License as published by
     5  the Free Software Foundation.
     6  
     7  Kuberpult is distributed in the hope that it will be useful,
     8  but WITHOUT ANY WARRANTY; without even the implied warranty of
     9  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    10  MIT License for more details.
    11  
    12  You should have received a copy of the MIT License
    13  along with kuberpult. If not, see <https://directory.fsf.org/wiki/License:Expat>.
    14  
    15  Copyright 2023 freiheit.com*/
    16  
    17  package repository
    18  
    19  import (
    20  	"bytes"
    21  	"context"
    22  	"encoding/base64"
    23  	"fmt"
    24  	"io"
    25  	"os"
    26  
    27  	"github.com/freiheit-com/kuberpult/pkg/logger"
    28  	git "github.com/libgit2/git2go/v34"
    29  	"go.uber.org/zap"
    30  	"golang.org/x/crypto/ssh"
    31  )
    32  
    33  type Credentials struct {
    34  	SshKey string
    35  }
    36  
    37  func base64encode(c []byte) string {
    38  	var buf bytes.Buffer
    39  	enc := base64.NewEncoder(base64.StdEncoding, &buf)
    40  	enc.Write(c) //nolint: errcheck
    41  	enc.Close()
    42  	return buf.String()
    43  }
    44  
    45  func (c *Credentials) load() (*credentialsStore, error) {
    46  	store := &credentialsStore{
    47  		sshPrivateKey: "",
    48  		sshPublicKey:  "",
    49  	}
    50  	if c.SshKey != "" {
    51  		pkey, err := os.Open(c.SshKey)
    52  		if err != nil {
    53  			return nil, err
    54  		}
    55  		defer pkey.Close()
    56  		privKeyContent, err := io.ReadAll(pkey)
    57  		if err != nil {
    58  			return nil, err
    59  		}
    60  		priv, err := ssh.ParsePrivateKey(privKeyContent)
    61  		if err != nil {
    62  			return nil, err
    63  		}
    64  		pubKeyContent := fmt.Sprintf("%s %s\n", priv.PublicKey().Type(), base64encode(priv.PublicKey().Marshal()))
    65  		store.sshPrivateKey = string(privKeyContent)
    66  		store.sshPublicKey = pubKeyContent
    67  	}
    68  	return store, nil
    69  }
    70  
    71  type credentialsStore struct {
    72  	sshPrivateKey string
    73  	sshPublicKey  string
    74  }
    75  
    76  func (c *credentialsStore) CredentialsCallback(ctx context.Context) git.CredentialsCallback {
    77  	if c == nil {
    78  		return func(url string, username_from_url string, allowed_types git.CredentialType) (*git.Credential, error) {
    79  			return nil, nil
    80  		}
    81  	}
    82  	logger := logger.FromContext(ctx)
    83  	return func(url string, username_from_url string, allowed_types git.CredentialType) (*git.Credential, error) {
    84  		logger.Debug("git.credentialsCallback",
    85  			zap.String("url", url),
    86  			zap.String("username", username_from_url),
    87  		)
    88  		if c.sshPrivateKey != "" && allowed_types|git.CredTypeSshKey != 0 {
    89  			return git.NewCredentialSSHKeyFromMemory(username_from_url, c.sshPublicKey, c.sshPrivateKey, "")
    90  		}
    91  		return nil, nil
    92  	}
    93  }