diff --git a/prow/cluster/deck_deployment.yaml b/prow/cluster/deck_deployment.yaml index 96831bceca1db..c3a51d9837690 100644 --- a/prow/cluster/deck_deployment.yaml +++ b/prow/cluster/deck_deployment.yaml @@ -39,6 +39,7 @@ spec: containerPort: 8080 args: - --jenkins-url=$(JENKINS_URL) + - --jenkins-token=/etc/jenkins/jenkins - --build-cluster=/etc/cluster/cluster env: - name: JENKINS_URL diff --git a/prow/cluster/jenkins_deployment.yaml b/prow/cluster/jenkins_deployment.yaml index 388d9ab45f031..4bedc4ea693f1 100644 --- a/prow/cluster/jenkins_deployment.yaml +++ b/prow/cluster/jenkins_deployment.yaml @@ -28,6 +28,7 @@ spec: image: gcr.io/k8s-prow/jenkins-operator:0.39 args: - --dry-run=false + - --jenkins-token=/etc/jenkins/jenkins volumeMounts: - mountPath: /etc/jenkins name: jenkins diff --git a/prow/cmd/deck/main.go b/prow/cmd/deck/main.go index f2cc5b2ff982a..97f12715acc26 100644 --- a/prow/cmd/deck/main.go +++ b/prow/cmd/deck/main.go @@ -39,9 +39,10 @@ var ( configPath = flag.String("config-path", "/etc/config/config", "Path to config.yaml.") buildCluster = flag.String("build-cluster", "", "Path to file containing a YAML-marshalled kube.Cluster object. If empty, uses the local cluster.") - jenkinsURL = flag.String("jenkins-url", "", "Jenkins URL") - jenkinsUserName = flag.String("jenkins-user", "jenkins-trigger", "Jenkins username") - jenkinsTokenFile = flag.String("jenkins-token-file", "/etc/jenkins/jenkins", "Path to the file containing the Jenkins API token.") + jenkinsURL = flag.String("jenkins-url", "", "Jenkins URL") + jenkinsUserName = flag.String("jenkins-user", "jenkins-trigger", "Jenkins username") + jenkinsTokenFile = flag.String("jenkins-token-file", "", "Path to the file containing the Jenkins API token.") + jenkinsBearerTokenFile = flag.String("jenkins-bearer-token-file", "", "Path to the file containing the Jenkins API bearer token.") ) // Matches letters, numbers, hyphens, and underscores. @@ -70,14 +71,30 @@ func main() { } } + var ac *jenkins.AuthConfig var jc *jenkins.Client if *jenkinsURL != "" { - jenkinsSecretRaw, err := ioutil.ReadFile(*jenkinsTokenFile) - if err != nil { - logrus.WithError(err).Fatalf("Could not read token file.") + if *jenkinsTokenFile != "" { + if token, err := loadToken(*jenkinsTokenFile); err != nil { + logrus.WithError(err).Fatalf("Could not read token file.") + } else { + ac.Basic = &jenkins.BasicAuthConfig{ + User: *jenkinsUserName, + Token: token, + } + } + } else if *jenkinsBearerTokenFile != "" { + if token, err := loadToken(*jenkinsBearerTokenFile); err != nil { + logrus.WithError(err).Fatalf("Could not read token file.") + } else { + ac.BearerToken = &jenkins.BearerTokenAuthConfig{ + Token: token, + } + } + } else { + logrus.Fatal("An auth token for basic or bearer token auth must be supplied.") } - jenkinsToken := string(bytes.TrimSpace(jenkinsSecretRaw)) - jc = jenkins.NewClient(*jenkinsURL, *jenkinsUserName, jenkinsToken) + jc = jenkins.NewClient(*jenkinsURL, ac) } ja := &JobAgent{ @@ -95,6 +112,14 @@ func main() { logrus.WithError(http.ListenAndServe(":8080", nil)).Fatal("ListenAndServe returned.") } +func loadToken(file string) (string, error) { + raw, err := ioutil.ReadFile(file) + if err != nil { + return "", err + } + return string(bytes.TrimSpace(raw)), nil +} + func handleData(ja *JobAgent) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Cache-Control", "no-cache") diff --git a/prow/cmd/jenkins-operator/main.go b/prow/cmd/jenkins-operator/main.go index 912ac4b96129a..cbd669015e26d 100644 --- a/prow/cmd/jenkins-operator/main.go +++ b/prow/cmd/jenkins-operator/main.go @@ -34,9 +34,10 @@ import ( var ( configPath = flag.String("config-path", "/etc/config/config", "Path to config.yaml.") - jenkinsURL = flag.String("jenkins-url", "http://jenkins-proxy", "Jenkins URL") - jenkinsUserName = flag.String("jenkins-user", "jenkins-trigger", "Jenkins username") - jenkinsTokenFile = flag.String("jenkins-token-file", "/etc/jenkins/jenkins", "Path to the file containing the Jenkins API token.") + jenkinsURL = flag.String("jenkins-url", "http://jenkins-proxy", "Jenkins URL") + jenkinsUserName = flag.String("jenkins-user", "jenkins-trigger", "Jenkins username") + jenkinsTokenFile = flag.String("jenkins-token-file", "", "Path to the file containing the Jenkins API token.") + jenkinsBearerTokenFile = flag.String("jenkins-bearer-token-file", "", "Path to the file containing the Jenkins API bearer token.") _ = flag.String("github-bot-name", "", "Deprecated.") githubEndpoint = flag.String("github-endpoint", "https://api.github.com", "GitHub's API endpoint.") @@ -58,12 +59,28 @@ func main() { logrus.WithError(err).Fatal("Error getting kube client.") } - jenkinsSecretRaw, err := ioutil.ReadFile(*jenkinsTokenFile) - if err != nil { - logrus.WithError(err).Fatalf("Could not read Jenkins token file.") + var ac *jenkins.AuthConfig + if *jenkinsTokenFile != "" { + token, err := loadToken(*jenkinsTokenFile) + if err != nil { + logrus.WithError(err).Fatalf("Could not read token file.") + } + ac.Basic = &jenkins.BasicAuthConfig{ + User: *jenkinsUserName, + Token: token, + } + } else if *jenkinsBearerTokenFile != "" { + token, err := loadToken(*jenkinsBearerTokenFile) + if err != nil { + logrus.WithError(err).Fatalf("Could not read bearer token file.") + } + ac.BearerToken = &jenkins.BearerTokenAuthConfig{ + Token: token, + } + } else { + logrus.Fatal("An auth token for basic or bearer token auth must be supplied.") } - jenkinsToken := string(bytes.TrimSpace(jenkinsSecretRaw)) - jc := jenkins.NewClient(*jenkinsURL, *jenkinsUserName, jenkinsToken) + jc := jenkins.NewClient(*jenkinsURL, ac) oauthSecretRaw, err := ioutil.ReadFile(*githubTokenFile) if err != nil { @@ -95,3 +112,11 @@ func main() { logrus.Infof("Sync time: %v", time.Since(start)) } } + +func loadToken(file string) (string, error) { + raw, err := ioutil.ReadFile(file) + if err != nil { + return "", err + } + return string(bytes.TrimSpace(raw)), nil +} diff --git a/prow/jenkins/jenkins.go b/prow/jenkins/jenkins.go index be85110c4f1e4..9c57a2cc38a77 100644 --- a/prow/jenkins/jenkins.go +++ b/prow/jenkins/jenkins.go @@ -43,10 +43,25 @@ type Status struct { } type Client struct { - client *http.Client - baseURL string - user string - token string + client *http.Client + baseURL string + authConfig *AuthConfig +} + +// AuthConfig configures how we auth with Jenkins. +// Only one of the fields will be non-nil. +type AuthConfig struct { + Basic *BasicAuthConfig + BearerToken *BearerTokenAuthConfig +} + +type BasicAuthConfig struct { + User string + Token string +} + +type BearerTokenAuthConfig struct { + Token string } type BuildRequest struct { @@ -64,12 +79,11 @@ type Build struct { QueueURL *url.URL } -func NewClient(url, user, token string) *Client { +func NewClient(url string, authConfig *AuthConfig) *Client { return &Client{ - baseURL: url, - user: user, - token: token, - client: &http.Client{}, + baseURL: url, + authConfig: authConfig, + client: &http.Client{}, } } @@ -97,7 +111,12 @@ func (c *Client) doRequest(method, path string) (*http.Response, error) { if err != nil { return nil, err } - req.SetBasicAuth(c.user, c.token) + if c.authConfig.Basic != nil { + req.SetBasicAuth(c.authConfig.Basic.User, c.authConfig.Basic.Token) + } + if c.authConfig.BearerToken != nil { + req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", c.authConfig.BearerToken.Token)) + } return c.client.Do(req) }