Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bitbucket server aka stash #194

Merged
merged 11 commits into from
Jul 25, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ atlantis server --gh-user <your username> --gh-token <your token> --repo-whiteli
```
ngrok http 4141
```
- Create a WebHook in your repo and use the `https` url that `ngrok` printed out after running `ngrok http 4141`. Be sure to append `/events` so your webhook url looks something like `https://efce3bcd.ngrok.io/events`. See [Add GitHub Webhook](https://github.com/runatlantis/atlantis#add-github-webhook).
- Create a Webhook in your repo and use the `https` url that `ngrok` printed out after running `ngrok http 4141`. Be sure to append `/events` so your webhook url looks something like `https://efce3bcd.ngrok.io/events`. See [Add GitHub Webhook](https://github.com/runatlantis/atlantis#add-github-webhook).
- Create a pull request and type `atlantis help`. You should see the request in the `ngrok` and Atlantis logs and you should also see Atlantis comment back.

## Code Style
Expand Down
109 changes: 66 additions & 43 deletions cmd/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,15 @@ package cmd

import (
"fmt"
"net/url"
"os"
"path/filepath"
"strings"

"github.com/mitchellh/go-homedir"
"github.com/pkg/errors"
"github.com/runatlantis/atlantis/server"
"github.com/runatlantis/atlantis/server/events/vcs/bitbucketcloud"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)
Expand All @@ -32,36 +34,37 @@ import (
// 3. Add your flag's description etc. to the stringFlags, intFlags, or boolFlags slices.
const (
// Flag names.
AllowForkPRsFlag = "allow-fork-prs"
AllowRepoConfigFlag = "allow-repo-config"
AtlantisURLFlag = "atlantis-url"
BitbucketHostnameFlag = "bitbucket-hostname"
BitbucketTokenFlag = "bitbucket-token"
BitbucketUserFlag = "bitbucket-user"
ConfigFlag = "config"
DataDirFlag = "data-dir"
GHHostnameFlag = "gh-hostname"
GHTokenFlag = "gh-token"
GHUserFlag = "gh-user"
GHWebHookSecret = "gh-webhook-secret" // nolint: gosec
GitlabHostnameFlag = "gitlab-hostname"
GitlabTokenFlag = "gitlab-token"
GitlabUserFlag = "gitlab-user"
GitlabWebHookSecret = "gitlab-webhook-secret" // nolint: gosec
LogLevelFlag = "log-level"
PortFlag = "port"
RepoWhitelistFlag = "repo-whitelist"
RequireApprovalFlag = "require-approval"
SSLCertFileFlag = "ssl-cert-file"
SSLKeyFileFlag = "ssl-key-file"
AllowForkPRsFlag = "allow-fork-prs"
AllowRepoConfigFlag = "allow-repo-config"
AtlantisURLFlag = "atlantis-url"
BitbucketBaseURLFlag = "bitbucket-base-url"
BitbucketTokenFlag = "bitbucket-token"
BitbucketUserFlag = "bitbucket-user"
BitbucketWebhookSecretFlag = "bitbucket-webhook-secret"
ConfigFlag = "config"
DataDirFlag = "data-dir"
GHHostnameFlag = "gh-hostname"
GHTokenFlag = "gh-token"
GHUserFlag = "gh-user"
GHWebhookSecretFlag = "gh-webhook-secret" // nolint: gosec
GitlabHostnameFlag = "gitlab-hostname"
GitlabTokenFlag = "gitlab-token"
GitlabUserFlag = "gitlab-user"
GitlabWebhookSecretFlag = "gitlab-webhook-secret" // nolint: gosec
LogLevelFlag = "log-level"
PortFlag = "port"
RepoWhitelistFlag = "repo-whitelist"
RequireApprovalFlag = "require-approval"
SSLCertFileFlag = "ssl-cert-file"
SSLKeyFileFlag = "ssl-key-file"

// Flag defaults.
DefaultBitbucketHostname = "bitbucket.org"
DefaultDataDir = "~/.atlantis"
DefaultGHHostname = "github.com"
DefaultGitlabHostname = "gitlab.com"
DefaultLogLevel = "info"
DefaultPort = 4141
DefaultBitbucketBaseURL = bitbucketcloud.BaseURL
DefaultDataDir = "~/.atlantis"
DefaultGHHostname = "github.com"
DefaultGitlabHostname = "gitlab.com"
DefaultLogLevel = "info"
DefaultPort = 4141
)

const RedTermStart = "\033[31m"
Expand All @@ -81,9 +84,18 @@ var stringFlags = []stringFlag{
description: "Bitbucket app password of API user. Can also be specified via the ATLANTIS_BITBUCKET_TOKEN environment variable.",
},
{
name: BitbucketHostnameFlag,
description: "Currently not supported! We only support bitbucket cloud (aka bitbucket.org) at this time.",
defaultValue: DefaultBitbucketHostname,
name: BitbucketBaseURLFlag,
description: "Base URL of Bitbucket Server (aka Stash) installation." +
" Must include scheme, ex. 'http://bitbucket.corp:7990' or 'https://bitbucket.corp'." +
" If using Bitbucket Cloud (bitbucket.org), do not set.",
defaultValue: DefaultBitbucketBaseURL,
},
{
name: BitbucketWebhookSecretFlag,
description: "Secret used to validate Bitbucket webhooks. Only Bitbucket Server supports webhook secrets." +
" SECURITY WARNING: If not specified, Atlantis won't be able to validate that the incoming webhook call came from Bitbucket. " +
"This means that an attacker could spoof calls to Atlantis and cause it to perform malicious actions. " +
"Should be specified via the ATLANTIS_BITBUCKET_WEBHOOK_SECRET environment variable.",
},
{
name: ConfigFlag,
Expand All @@ -108,7 +120,7 @@ var stringFlags = []stringFlag{
description: "GitHub token of API user. Can also be specified via the ATLANTIS_GH_TOKEN environment variable.",
},
{
name: GHWebHookSecret,
name: GHWebhookSecretFlag,
description: "Secret used to validate GitHub webhooks (see https://developer.github.com/webhooks/securing/)." +
" SECURITY WARNING: If not specified, Atlantis won't be able to validate that the incoming webhook call came from GitHub. " +
"This means that an attacker could spoof calls to Atlantis and cause it to perform malicious actions. " +
Expand All @@ -128,7 +140,7 @@ var stringFlags = []stringFlag{
description: "GitLab token of API user. Can also be specified via the ATLANTIS_GITLAB_TOKEN environment variable.",
},
{
name: GitlabWebHookSecret,
name: GitlabWebhookSecretFlag,
description: "Optional secret used to validate GitLab webhooks." +
" SECURITY WARNING: If not specified, Atlantis won't be able to validate that the incoming webhook call came from GitLab. " +
"This means that an attacker could spoof calls to Atlantis and cause it to perform malicious actions. " +
Expand All @@ -143,7 +155,8 @@ var stringFlags = []stringFlag{
name: RepoWhitelistFlag,
description: "Comma separated list of repositories that Atlantis will operate on. " +
"The format is {hostname}/{owner}/{repo}, ex. github.com/runatlantis/atlantis. '*' matches any characters until the next comma and can be used for example to whitelist " +
"all repos: '*' (not recommended), an entire hostname: 'internalgithub.com/*' or an organization: 'github.com/runatlantis/*'.",
"all repos: '*' (not recommended), an entire hostname: 'internalgithub.com/*' or an organization: 'github.com/runatlantis/*'." +
" For Bitbucket Server, {hostname} is the domain without scheme and port, {owner} is the name of the project (not the key), and {repo} is the repo name.",
},
{
name: SSLCertFileFlag,
Expand Down Expand Up @@ -343,8 +356,8 @@ func (s *ServerCmd) setDefaults(c *server.UserConfig) {
if c.GitlabHostname == "" {
c.GitlabHostname = DefaultGitlabHostname
}
if c.BitbucketHostname == "" {
c.BitbucketHostname = DefaultBitbucketHostname
if c.BitbucketBaseURL == "" {
c.BitbucketBaseURL = DefaultBitbucketBaseURL
}
if c.LogLevel == "" {
c.LogLevel = DefaultLogLevel
Expand All @@ -364,10 +377,6 @@ func (s *ServerCmd) validate(userConfig server.UserConfig) error {
return fmt.Errorf("--%s and --%s are both required for ssl", SSLKeyFileFlag, SSLCertFileFlag)
}

if userConfig.BitbucketHostname != DefaultBitbucketHostname {
return fmt.Errorf("--%s is currently not allowed because we only support bitbucket cloud", BitbucketHostnameFlag)
}

// The following combinations are valid.
// 1. github user and token set
// 2. gitlab user and token set
Expand All @@ -390,6 +399,17 @@ func (s *ServerCmd) validate(userConfig server.UserConfig) error {
return fmt.Errorf("--%s cannot contain ://, should be hostnames only", RepoWhitelistFlag)
}

if userConfig.BitbucketBaseURL == DefaultBitbucketBaseURL && userConfig.BitbucketWebhookSecret != "" {
return fmt.Errorf("--%s cannot be specified for Bitbucket Cloud because it is not supported by Bitbucket", BitbucketWebhookSecretFlag)
}

parsed, err := url.Parse(userConfig.BitbucketBaseURL)
if err != nil {
return fmt.Errorf("error parsing --%s flag value %q: %s", BitbucketWebhookSecretFlag, userConfig.BitbucketBaseURL, err)
}
if parsed.Scheme != "http" && parsed.Scheme != "https" {
return fmt.Errorf("--%s must have http:// or https://, got %q", BitbucketBaseURLFlag, userConfig.BitbucketBaseURL)
}
return nil
}

Expand Down Expand Up @@ -437,13 +457,16 @@ func (s *ServerCmd) trimAtSymbolFromUsers(userConfig *server.UserConfig) {
}

func (s *ServerCmd) securityWarnings(userConfig *server.UserConfig) {
if userConfig.GithubUser != "" && userConfig.GithubWebHookSecret == "" && !s.SilenceOutput {
if userConfig.GithubUser != "" && userConfig.GithubWebhookSecret == "" && !s.SilenceOutput {
fmt.Fprintf(os.Stderr, "%s[WARN] No GitHub webhook secret set. This could allow attackers to spoof requests from GitHub.%s\n", RedTermStart, RedTermEnd)
}
if userConfig.GitlabUser != "" && userConfig.GitlabWebHookSecret == "" && !s.SilenceOutput {
if userConfig.GitlabUser != "" && userConfig.GitlabWebhookSecret == "" && !s.SilenceOutput {
fmt.Fprintf(os.Stderr, "%s[WARN] No GitLab webhook secret set. This could allow attackers to spoof requests from GitLab.%s\n", RedTermStart, RedTermEnd)
}
if userConfig.BitbucketUser != "" && userConfig.BitbucketHostname == DefaultBitbucketHostname && !s.SilenceOutput {
if userConfig.BitbucketUser != "" && userConfig.BitbucketBaseURL != DefaultBitbucketBaseURL && userConfig.BitbucketWebhookSecret == "" && !s.SilenceOutput {
fmt.Fprintf(os.Stderr, "%s[WARN] No Bitbucket webhook secret set. This could allow attackers to spoof requests from Bitbucket.%s\n", RedTermStart, RedTermEnd)
}
if userConfig.BitbucketUser != "" && userConfig.BitbucketBaseURL == DefaultBitbucketBaseURL && !s.SilenceOutput {
fmt.Fprintf(os.Stderr, "%s[WARN] Bitbucket Cloud does not support webhook secrets. This could allow attackers to spoof requests from Bitbucket. Ensure you are whitelisting Bitbucket IPs.%s\n", RedTermStart, RedTermEnd)
}
}
Expand Down
Loading