티스토리 뷰
개요
Slack slash command 가 메시지를 보내올때에, 그것이 Slack 에서 보내온 것인지 검증해보자.
링크: https://api.slack.com/docs/verifying-requests-from-slack
(참고) 현재까지 관련 포스팅 모음
- Golang: Github - Travis-CI - Heroku: https://jusths.tistory.com/69
- Slack slash command + Golang server: https://jusths.tistory.com/72
- slack slash command 는 무얼 보내주는 걸까: https://jusths.tistory.com/73
Signing secret
Slack 에 앱을 등록하면 Slack 은 unique 한 string 인 Signing secret 을 생성해준다.
우리는 Signing secret 을 이용하여 Vefification 을 수행한다.
→ 즉, Golang 서버가 Slack 에서 보냈다는 HTTP POST message 를 받으면, 정말 Slack 에서 보냈는지를 검증한다.
https://api.slack.com 에서 App 의 Basic Information 을 보면 Signing secret 정보를 확인할 수 있다.
프로세스는 다음과 같다.
Slack 은 설정에 등록된 우리의 Golang 서버에 다음과 같이 signature 를 붙여서 HTTP POST request 를 보낸다.
1) Slack 은 (당연히) 앱의 Signing secret 을 가지고 있고, Golang 서버 역시 동일한 정보를 알고 있도록 한다. (환경변수 등등)
2) Slack 은 Signing secret 과 전송하려는 body 로 HMAC 을 이용하여 signature 를 만든다.
- HMAC 참고: standard HMAC-SHA256 keyed hash
3) Slack 이 보내는 HTTP POST header 의 X-Slack-Signature 에 바로 이렇게 만든 signature 가 들어간다.
- 보내려는 내용인 body 에
- Signing secret 으로 서명 작업을 하면 나오는 것이
- 바로 body 의 signature 인 것이다.
→ 그래서 body 마다 고유의 signature 를 가지게 된다.
그러면 HTTP POST 를 받은 Golang server 다음과 같은 작업을 하게 된다.
1) Golang server 는 Slack 과 똑같은 Sigining secret 을 가지고 있다.
2) Signing secret 과 받은 HTTP POST 의 body 로 HMAC 을 이용하여 signature 를 만든다.
3) 이렇게 Golang server 가 만든 singature 와 HTTP POST header 의 X-Slack-Signature (= Slack 이 만든 signature) 의 값이 같은지를 확인한다. 똑같다면 verified!
이렇게 하면 다음과 같은 강점을 가지게 된다.
1) request 마다 body 가 바뀌니 매번 unique 한 signature 가 생성된다.
2) Slack 과 Golang server 가 공유한 Signing secret 정보는 HTTP POST request 에 들어가지 않는다.
(참고) Go 말고 다른 언어들 - Node, Python 용 SDK 는 있음
- https://api.slack.com/docs/verifying-requests-from-slack#sdk_support
Golang server 에서 signature 만들기
필요한 재로는 다음과 같다.
1) Slack 에서 온 HTTP POST request
2) signing 에 사용될 Signing secret (슬랙이 생성해서 앱에 공유해준거)
3) 사용할 프로그래밍 언어 - 우리는 Golang
* 파이썬 구현 참고: https://goo.gl/9Ttqci
파이썬의 구현코드를 참고하여 프로세스를 정리해보면 다음과 같다.
1) Slack HTTP POST request 에서 X-Slack-Request-Timestamp 와 body 를 가져온다. 2) version number + timestamp + body 를 basestrintg 으로 concatenate 해준다. - ex) v0:123456789:command=/weather&text=94070 3) 위의 basestring 을, Server 가 가지고 있는 Signing secret 을 key 로 하여, 4) 프로그래밍 언어가 제공하는 HMAC SHA256 을 이용해 signing 한다. 5) Request Header 의 X-Slack-Signature 값과 생성한 값이 같으면 verify |
Step-by-step 으로 알아보자
1) Signing secret
- https://api.slack.com 에서 App 의 Basic Information 을 보면 Signing secret 정보를 확인할 수 있다.
- utf-8 포맷의 string 이라 생각하자.
- ex) 8f742231b10e8888abcd99yyyzzz85a5
2) Request body 추출
- HTTP POST request 를 Parsing 하면 아래와 같은 body 값을 얻을 수 있다.
token=xyzz0WbapA4vBCDEFasx0q6G&team_id=T1DC2JH3J&team_domain=testteamnow&channel_id=G8PSS9T3V&channel_name=foobar&user_id=U2CERLKJA&user_name=roadrunner&command=%2Fwebhook-collect&text=&response_url=https%3A%2F%2Fhooks.slack.com%2Fcommands%2FT1DC2JH3J%2F397700885554%2F96rGlfmibIGlgcZRskXaIFfN&trigger_id=398738663015.47445629121.803a0bc887a14d10d2c447fce8b6703c |
3) Timestamp 주출
- 마찬가지로 다음과 같은 포맷의 timestamp 를 얻을 수 있다 (UNIX time): 1531420618
→ Timestamp 는 replay attack 대비로 의미가 있다.
→ replay attack 체크로 현재시간보다 5분이상 지난건 버려버리는 것도 좋다.
4) 합체 (Concatenate)
- 버전:타임스탬프:바디 합체
- delimiter 는 colon, 즉 ":" 이다.
5) signing secret 으로 위 합체 스트링을 hash 해준다.
- 그리고 hash 결과인 string 의 앞에 "v0=" 을 붙여준다.
예를 들어
- hash 결과: a2114d57b48eac39b9ad189dd8316235a7b4a8d21a10bd27519666489c69b503
- "v0=" 붙여주기: v0=a2114d57b48eac39b9ad189dd8316235a7b4a8d21a10bd27519666489c69b503
6) 비교
위 결과와 Request header 의 signature 를 비교해서 같으면 OK
기타등등
- Signing secret 이 유출되었다면 울지말고 새로 생성하면 됨.
- JSON 이나 다른 것으로 deserialize 되기전의 raw request body 를 사용할 것
'golang' 카테고리의 다른 글
Go Modules - Local Modules (0) | 2019.04.10 |
---|---|
Slack slash command: Verifying requests from Slack: code (0) | 2019.02.25 |
Golang Channel 의 자명한 이치 (Axioms) (0) | 2019.02.18 |
slack slash command 는 무얼 보내주는 걸까 (0) | 2019.02.15 |
Slack slash command + Golang server (0) | 2019.02.12 |
- Total
- Today
- Yesterday
- pool
- 잡학툰
- 영화
- Bug
- 2023
- Shortcut
- 클린 애자일
- notion
- Gin
- websocket
- OpenAI
- API
- go
- 노션
- 체호프
- golang
- JIRA
- 독서
- agile
- 독서후기
- strange
- folklore
- ChatGPT
- 제이펍
- intellij
- bun
- 인텔리제이
- solid
- github
- postgres
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |