Go로 Slack Bot 만들기

Sangdae Nam·2023년 8월 7일
0
post-thumbnail
  1. 본 글은 앞선 govulncheck 글에서 이어지는 글이다.
    특정 프로그램의 패키지 취약성을 alarm 줄 수 있는 슬랙 봇을 만들어 보려고 한다.
  2. Slack Bot 세팅
    나는 회사 슬랙에 있는 특정 채널의 web-hook url을 사용하였지만 본 글에서는 시연을 위해 슬랙 워크스페이스를 새로 하나 만들고 따로 세팅을 하려고 한다.해당 글을 읽는 분들 중 슬랙 채널이 따로 있거나 web-hook url이 따로 있을 경우 아래 세팅 과정을 생략하여도 된다.
    1) Slack 홈페이지에서 Create your first app 을 클릭한다. Create App
    2) 위 create app을 들어간 다음 From Scratch를 클릭하면 다음과 같은 화면이 뜬다. 여기서 본인이 만들고 싶은 슬랙 봇의 이름과 워크스페이스를 설정하면 앱이 하나 만들어진다. app setting
    3) 이후 해당 앱에 여러가지 세팅을 할 수 있다. 이제 web-hook url을 설정해보자. 세팅 중 Incoming Webhooks에 들어가면 Webhook을 add 할 수 있다. 여기서 본인이 해당 앱을 통한 내용을 전달 받고 싶은 채널을 선택하면 url이 생성된다. basic setting url setting
    4) 아래 이미지와 같이 잘 생성된 것을 볼 수 있다. 이제 이 url을 복사하여 사용할 것이다. result
  3. 코드 작성
    본 프로그램에서는 golang의 slack-api 라이브러리를 사용할 것이다. 자세한 내용은 document에서 볼 수 있다. https://pkg.go.dev/github.com/slack-go/slack
    기본적으로 slack의 PostWebhookContext에 web-hook url과 메세지를 함께 전달하는 방식으로 작동하며, 해당 메시지에 대해서는 여러 스타일 적용이 가능하다. 여기서는 간단하게 어떤 패키지 취약성이 나타났는지 govulncheck의 메세지를 그대로 담아서 전달하려고 한다.
func SendPackageVulnerabilityBatch(ctx context.Context, url string, message string) error {
	return slack.PostWebhookContext(ctx, url, &slack.WebhookMessage{
		Blocks: &slack.Blocks{
			BlockSet: []slack.Block{
				slack.NewSectionBlock(&slack.TextBlockObject{
					Type: slack.MarkdownType,
					Text: "Vulnerability Check",
				}, nil, nil),
			},
		},
		Attachments: []slack.Attachment{
			{
				Color: "#ff7f00",
				Blocks: slack.Blocks{
					BlockSet: append([]slack.Block{
						slack.NewSectionBlock(&slack.TextBlockObject{
							Type: slack.MarkdownType,
							Text: message,
						}, nil, nil),
					}),
				},
			},
		},
	})
}
  1. Test 코드 작성
    해당 함수가 잘 작동하는지 보기 위한 테스트 코드를 작성하고 우리가 받고 싶은 채널로 내용이 잘 오는지 확인할 수 있다. 아래 정보에 여러분이 아까 복사한 web-hook url을 넣으면 된다. 이때 주의해야할 점이 하나 있는데 go에서 패키지라 하면 여러분의 프로젝트의 가장 기본 directory(base_dir이라고 하겠다)의 go.mod에 정의된다. 그리고 해당 base_dir에서 패키지 govulncheck이 실행이 되어야 우리가 사용하는 패키지들에 대한 진단이 가능하다. 하지만 해당 slack alarm 코드가 base_dir에서 더 들어간 다른 패키지 내에서 수행된다면 해당 프로세스에서 단순히 govulncheck을 실행할 경우 프로그램 전반에 대한 패키지 취약성 검사가 불가능하다. 따라서 해당 프로세스가 진행되는 path를 찾고 거기서 base_dir를 찾아서 거기에 govulncheck을 한 뒤 그 결과를 slack에 전달해주는 코드로 작성하였다.
func TestSlackVulnCheck(t *testing.T) {
	ctx := context.Background()
	assert := assert.New(t)
	urlTemp := "https://hooks.slack.com/services/.." <- 여러분의 web-hook url
    
    base_dir = "main"

	_, b, _, _ := runtime.Caller(0)
	d := path.Join(path.Dir(b))
	res := strings.Split(d, base_dir)
	p := path.Join(res[0], base_dir) + "/..."
	cmd := exec.Command("govulncheck", p)

	output, err := cmd.CombinedOutput()

	fmt.Println(string(output))

	err = SendPackageVulnerabilityBatch(ctx, urlTemp, string(output))

	assert.Nil(err)
}
  1. 결과
    아래와 같이 govulncheck로 패키지 취약성을 진단한 내용이 슬랙으로 잘 전달 된 것을 볼 수 있다.
    slack-result
profile
AI+Backend

0개의 댓글