ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

基于golang+openssh 服务实现一个简单的git over ssh 服务

2022-02-22 20:32:23  阅读:291  来源: 互联网

标签:git openssh over com ssh https os


昨天看了开源的codefever 以及以前简单学习过gogs,刚才学习下git over ssh 的实现机制
基于openssh + golang (golang 部分参考了gogs 处理)实现了一个简单的git server (ssh 协议的)

原理说明

核心还是我们的openssh server 创建一个git 账户,此账户使用了authorized_keys的forcecommand 功能
forcecommand 中我们添加了git 的处理

  • forcecommand 代码
 
package main
 
import (
    "fmt"
    "log"
    "os"
    "os/exec"
    "strings"
)
 
func init() {
    file := "./" + "message" + ".txt"
    logFile, err := os.OpenFile(file, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0766)
    if err != nil {
        panic(err)
    }
    log.SetOutput(logFile)
    log.SetFlags(log.LstdFlags | log.Lshortfile | log.LUTC)
}
func parseSSHCmd(cmd string) (string, string) {
    ss := strings.SplitN(cmd, " ", 2)
    if len(ss) != 2 {
        return "", ""
    }
    return ss[0], strings.Replace(ss[1], "'/", "'", 1)
}
func main() {
  // forcecommand 会包含一个SSH_ORIGINAL_COMMAND 里边是git 的一些操作命令,包含了具体命令的处理
    println(os.Getenv("SSH_ORIGINAL_COMMAND"))
    sshCmd := os.Getenv("SSH_ORIGINAL_COMMAND")
    verb, args := parseSSHCmd(sshCmd)
    repoFullName := strings.ToLower(strings.Trim(args, "'"))
    verbs := strings.Split(verb, " ")
    var gitCmd *exec.Cmd
    gitRepoPath := fmt.Sprintf("/opt/gitrepo/%s", repoFullName)
    os.Setenv("MY_UID", "dalongrong")
    if len(verb) == 2 {
        println(verbs[0], verbs[1], gitRepoPath)
        gitCmd = exec.Command(verbs[0], verbs[1], gitRepoPath)
    } else {
        println(verbs[0], gitRepoPath)
        gitCmd = exec.Command(verb, gitRepoPath)
    }
    gitCmd.Stdin = os.Stdin
    gitCmd.Stdout = os.Stdout
    gitCmd.Stderr = os.Stderr
    if err := gitCmd.Run(); err != nil {
        log.Fatal("Internal error", "Failed to execute git command: %v", err)
    }
    return
}

docker 构建

FROM golang:1.17-alpine AS build-env
WORKDIR /go/src/app
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories
 
ENV  GO111MODULE=on
ENV  GOPROXY=https://goproxy.cn
COPY . .
RUN apk update && apk add git \
    && go build -o git-shell
 
FROM alpine:latest
WORKDIR /app
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories
RUN apk update && apk add ca-certificates && rm -rf /var/cache/apk/*
COPY --from=build-env /go/src/app/git-shell /app/git-shell
  • authorized_keys 配置格式
    目前比较简单,没有进行复杂的校验处理
    command 部分使用了自己开发的git 处理
 
command="/opt/git-shell",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty  <ssh public key>
  • openssh 服务启动
    基于docker-compose 运行
 
version: '3'
services:
  ssh:
    image: dalongrong/openssh-server
    build: ./
    environment:
      - PUID=1000
      - PGID=1000
      - TZ=Asia/Shanghai
      - SUDO_ACCESS=true #optional
      - PASSWORD_ACCESS=true #optional
      - USER_PASSWORD=dalongdemo #optional
      - USER_NAME=git #optional
    volumes:
      - ./config:/config
      - ./gitrepo:/opt/gitrepo
    ports:
      - "2222:2222"

使用说明

  • 创建bare git repo
    启动之后我们需要创建git repo 注意是bare 模式的
    进入openssh 容器
 
su git 
cd /opt/gitrepo
git init  --bare demoapp2.git

效果

 

 

  • 添加ssh 认证客户
    config的.ssh 文件夹中的authorized_keys 格式如上
  • clone 代码
 
git clone  ssh://git@localhost:2222/demoapp2.git demoapp2

效果

 

 


push 代码

 
cd demoapp2
touch rong.txt
git add --all
git commit -m "add"
git push

效果

 

 

说明

如果有权限的问题就可能需要设置先权限了(openssh 容器内执行)

 
chmod 0755 /opt/gitrepo  /config
chmod 700 /config/.ssh

以上是一个简单的学习,参考了gogs、gitlab 等开源项目,基于此刚才对于git ssh server 就有了一个比较完整的了解
完整代码已经放github 了,大家可以参考,实际上目前一些开源的git 支持ssh 协议的基本都是这个套路,只是authorized_keys
的forcecommand 处理上大家好多是不一样的,而且新版本的gitlab 已经自己写了一个ssh server,同时推荐基于AuthorizedKeysCommand
更好的优化处ssh key 的处理了

参考资料

https://github.com/rongfengliang/write-one-git-ssh-server
https://github.com/gogs/gogs
https://github.com/PGYER/codefever
https://git-scm.com/docs/git-receive-pack
https://git-scm.com/docs/git-upload-pack
https://www.ssh.com/academy/ssh/authorized_keys/openssh
https://blog.scalesec.com/just-in-time-ssh-provisioning-7b20d9736a07
https://git-scm.com/book/zh/v2/Git-%E5%86%85%E9%83%A8%E5%8E%9F%E7%90%86-%E4%BC%A0%E8%BE%93%E5%8D%8F%E8%AE%AE
https://git-scm.com/docs/pack-protocol/2.2.3

标签:git,openssh,over,com,ssh,https,os
来源: https://www.cnblogs.com/rongfengliang/p/15924816.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有