github.com/inteleradmedicalsystems/go-codecommit@v0.1.0/pkg/codecommit/codecommit.go (about)

     1  package codecommit
     2  
     3  import (
     4  	"fmt"
     5  	nurl "net/url"
     6  	"regexp"
     7  	"strings"
     8  	"time"
     9  
    10  	"github.com/aws/aws-sdk-go/aws/credentials"
    11  	"github.com/aws/aws-sdk-go/aws/endpoints"
    12  	"github.com/aws/aws-sdk-go/aws/session"
    13  )
    14  
    15  //
    16  var RegionRe *regexp.Regexp
    17  
    18  func init() {
    19  	RegionRe = regexp.MustCompile(`git-codecommit\.([^.]+)\.amazonaws\.com`)
    20  }
    21  
    22  //IsCodeCommitURL return true if the url is for a CodeCommit Git repo.
    23  func IsCodeCommitURL(url string) bool {
    24  	u, err := nurl.Parse(url)
    25  	if err != nil {
    26  		return false
    27  	}
    28  	return RegionRe.MatchString(u.Host)
    29  }
    30  
    31  //NewCloneURL return CloneURL object for CodeCommit
    32  func NewCloneURL(sess *session.Session, url string) (*CloneURL, error) {
    33  	var err error
    34  	if creds, err := sess.Config.Credentials.Get(); err == nil {
    35  		c := &CloneURL{
    36  			RawURL:     url,
    37  			CredValues: creds,
    38  		}
    39  		if err = c.setURL(); err == nil {
    40  			return c, nil
    41  		}
    42  	}
    43  	return nil, err
    44  }
    45  
    46  type CloneURL struct {
    47  	RawURL     string
    48  	CredValues credentials.Value
    49  	u          *nurl.URL
    50  }
    51  
    52  func (c *CloneURL) setURL() error {
    53  	u, err := nurl.Parse(c.RawURL)
    54  	if err != nil {
    55  		return err
    56  	}
    57  	c.u = u
    58  	return nil
    59  }
    60  
    61  //
    62  func (c *CloneURL) buildCloneURL() error {
    63  	err := c.setURL()
    64  	if err != nil {
    65  		return err
    66  	}
    67  	if c.u.User == nil && strings.Split(c.u.Hostname(), ".")[0] == "git-codecommit" {
    68  		if err = c.addCodeCommitCreds(); err != nil {
    69  			return err
    70  		}
    71  	}
    72  	return err
    73  }
    74  
    75  // Include the CodeCommit HTTP AUTH params .
    76  func (c *CloneURL) addCodeCommitCreds() error {
    77  	if creds, err := c.GetCodeCommitCredentials(); err == nil {
    78  		c.u.User = nurl.UserPassword(creds.Username, creds.Password)
    79  	} else {
    80  		return err
    81  	}
    82  	return nil
    83  }
    84  
    85  func (c *CloneURL) String() string {
    86  	err := c.buildCloneURL()
    87  	if err != nil {
    88  		return ""
    89  	}
    90  	return c.u.String()
    91  }
    92  
    93  //GetCodeCommitCredentials return CodeCommitCredentials for URL
    94  func (c *CloneURL) GetCodeCommitCredentials() (*CodeCommitCredentials, error) {
    95  	region, err := c.parseRegion()
    96  	if err != nil {
    97  		return nil, err
    98  	}
    99  
   100  	ctx := NewSigningContext(c.u, region, endpoints.CodecommitServiceID, c.CredValues, time.Now())
   101  	username := c.CredValues.AccessKeyID
   102  	if c.CredValues.SessionToken != "" {
   103  		username = fmt.Sprintf("%s%%%s", username, c.CredValues.SessionToken)
   104  	}
   105  
   106  	return &CodeCommitCredentials{
   107  		Username: username,
   108  		Password: ctx.signCodeCommitRequest(),
   109  	}, nil
   110  }
   111  
   112  func (c *CloneURL) parseRegion() (string, error) {
   113  	if c.u == nil {
   114  		return "", fmt.Errorf("url is not set")
   115  
   116  	}
   117  	match := RegionRe.FindStringSubmatch(c.u.Host)
   118  	if match != nil {
   119  		return match[1], nil
   120  	}
   121  
   122  	return "", fmt.Errorf("invalid CodeCommit URL %q", c.u.String())
   123  }
   124  
   125  type CodeCommitCredentials struct {
   126  	Username string
   127  	Password string
   128  }