V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
hadesy
V2EX  ›  问与答

gitlab 许可证疑问

  •  
  •   hadesy · 2018-10-23 10:32:57 +08:00 · 9750 次点击
    这是一个创建于 1301 天前的主题,其中的信息可能已经有所发展或是发生改变。
    看了下 gitlab-ee 的许可证策略,发现十分简单,基本没有做防破解的策略,是还有更深的埋点还是说就是就是这样的?
    25 条回复    2020-05-20 05:00:46 +08:00
    xbsura
        1
    xbsura  
       2018-11-27 11:34:54 +08:00
    最近也在看, 因为 merge request approve 的问题, 纠结买不买, 一个月过去了, 试用应该过期了, 楼主啥结论
    hadesy
        2
    hadesy  
    OP
       2019-01-04 11:57:45 +08:00
    @xbsura 自签发,没有问题
    CodeCommunist
        3
    CodeCommunist  
       2019-01-16 08:06:58 +08:00
    @hadesy 用那个免费 license 再签发一个吗,具体怎么做,这跟 ssl 证书一样吗
    hadesy
        4
    hadesy  
    OP
       2019-01-20 16:43:40 +08:00   ❤️ 1
    CodeCommunist
        5
    CodeCommunist  
       2019-01-27 12:30:12 +08:00 via Android
    @hadesy 我大概看了一下,原理大概跟 ssl 差不多,就是替换自己的公钥,然后用自己的私钥签发一个 license,请教一下 license 格式是怎样的,我在官方源码找不到啊。世界上最好的语言没学过,Ruby 带注释我还能大概猜出来。
    hadesy
        6
    hadesy  
    OP
       2019-01-28 12:00:31 +08:00
    @CodeCommunist license 格式,你可以申请一个官方的试用许可证,然后 decrypt 出来看就了解了
    gkl1368
        7
    gkl1368  
       2019-02-22 17:36:05 +08:00
    @hadesy 请问如何签发 license ?
    srainbow
        8
    srainbow  
       2019-03-13 17:14:36 +08:00
    @hadesy 请问下, 看 ruby 那个代码,是生成 rsa 2048 的私钥,再生成一个公钥?

    使用最新版的 docker 镜像,使用 @hadesy 的 php 代码 生成一个许可证,直接提示 500
    CoderYellow
        9
    CoderYellow  
       2019-10-23 10:56:41 +08:00
    被 DMCA takedown 能发一下代码吗
    xdfer16
        10
    xdfer16  
       2019-10-31 17:30:40 +08:00
    看到一个 java 的代码,生成后,可以用,但是导入之后 gitlab 导入 license 那个界面 500error 了,换成 ruby 代码生成的公钥没有问题,但是 plan 只能是 starter.
    hadesy
        11
    hadesy  
    OP
       2019-10-31 21:02:58 +08:00
    @xdfer16 原理很简单的,就是一个 aes-128-cbc,500 可以去看 log
    datafeng
        12
    datafeng  
       2019-11-14 22:24:46 +08:00
    有人研究出 github enterprise 的怎么搞吗?
    看了几篇文章都是把关键部分跳过了。
    GreatZhwt
        13
    GreatZhwt  
       2019-11-18 22:07:51 +08:00
    @xdfer16 我刚折腾完发现也是 starter, 有点怀疑 plan 不对是不是因为生成的 license 里面缺少一点东西, 主要是目前没有更高级别的 license 作参考
    GreatZhwt
        14
    GreatZhwt  
       2019-11-19 01:50:40 +08:00
    @xdfer16 折腾出来了, 目前我的版本是 12.4.2-ee (a3170599aa2), 修改 /opt/gitlab/embedded/service/gitlab-rails/ee/app/models/license.rb 这个文件的 353 行, 把 STARTER_PLAN 修改为 ULTIMATE_PLAN 就可以了
    yealinkjobpan
        15
    yealinkjobpan  
       2019-12-01 15:14:02 +08:00
    @GreatZhwt 最近也在研究,能提供一下代码参考一下吗,谢谢。
    GreatZhwt
        16
    GreatZhwt  
       2019-12-16 13:59:45 +08:00
    @yealinkjobpan 没有改 gitlab 源代码啊 只是用官方套件签发了一个 license, 然后替换掉原有的公钥文件就可以了
    godymoon
        17
    godymoon  
       2019-12-18 15:20:50 +08:00
    @GreatZhwt 能详细说一下步骤吗?
    mayershi
        18
    mayershi  
       2019-12-23 14:54:34 +08:00
    qq296015668
        19
    qq296015668  
       2020-01-09 15:36:02 +08:00
    @datafeng 我也在研究,新版本的代码头还取消了 require,代码倒是解出来了,但是太多了,完全不知道关键的代码在哪。。头疼
    qq296015668
        20
    qq296015668  
       2020-01-09 15:45:14 +08:00
    @datafeng 许可证格式跟 gitlab 的差不多,gpg -d 你的 lic 文件就能看到内容了
    参考 gitlab 的话,可以看看这个文件 /data/github/dcddc67b84a7b1b7d8102b5ec879d486e7308921/vendor/gems/2.6.4/ruby/2.6.0/gems/enterprise-crypto-0.4.14/lib/enterprise/crypto/license.rb
    里面有创建新授权的代码,看看怎么使用
    qq296015668
        21
    qq296015668  
       2020-01-09 15:48:28 +08:00
    @datafeng
    ```
    module Enterprise
    module Crypto
    # An enterprise install license. Contains metadata about the
    # enterprise install (such as the customer license, seat count, etc.)
    # and an open set of files that are overlayed on the enterprise
    # VM instance.
    #
    class License < Struct.new(:customer, :metadata, :files)
    extend SafeDir
    include Tar

    # Creates a new license for the customer.
    #
    # customer - a Customer object which represents the enterprise customer.
    # seats - an Integer of the total customer seat count.
    # expire_at - a DateTime of when the license expires.
    # support_key - an optional public rsa/dsa key for SSH access.
    # metadata - a Hash of extra data that describes the license.
    # files - an optional set of files to be placed on the VM.
    #
    def self.generate(customer, seats, expire_at, support_key = nil, extra_metadata = {}, files = {})
    metadata = extra_metadata.inject({}) {|h, (k,v)| h.update(k.to_s => v) }

    license = new(customer, metadata, files)

    license.company = customer.name
    license.seats = seats
    license.expire_at = expire_at
    license.customer_private_key = customer.secret_key_data
    license.customer_public_key = customer.public_key_data
    license.support_key = support_key unless support_key.nil?

    license
    end

    # Reads and loads a license from raw license data.
    #
    # asc_data - the encrypted & signed license data.
    #
    def self.load(asc_data, vault = Crypto.license_vault, tmp = mktmpdir.to_path)
    tar_file = Crypto.with_vault(vault) do
    vault.read_license(asc_data)
    end

    if from_tar(tar_file, tmp)
    from_dir(tmp)
    else
    raise Error.new("Tar failed to extract: #{tar_file} to #{tmp}")
    end
    ensure
    # Remove the extration directory.
    # We don't need it around for anything.
    FileUtils.rm_rf tmp
    end

    # Serializes this license to binary data.
    #
    def to_bin(vault = Crypto.license_vault)
    lic_dir = to_dir
    lic_tar = to_tar(lic_dir)
    Crypto.with_vault(vault) do
    vault.generate_license(lic_tar)
    end
    ensure
    FileUtils.rm_rf lic_tar
    FileUtils.rm_rf lic_dir
    FileUtils.rm_rf tmpdir
    end

    def company
    metadata['company']
    end

    def company=(c)
    metadata['company'] = c
    end

    def seats
    metadata['seats']
    end

    def seats=(count)
    metadata['seats'] = count.to_i
    end

    def evaluation
    !!metadata['evaluation']
    end
    alias evaluation? evaluation

    def evaluation=(value)
    metadata['evaluation'] = value
    end

    def expire_at
    DateTime.parse(metadata['expire_at'])
    end

    def expire_at=(time)
    metadata['expire_at'] = DateTime.parse(time.to_s).to_s
    end

    def customer_public_key
    metadata['customer_public_key']
    end

    def customer_public_key=(value)
    metadata['customer_public_key'] = value
    end

    def customer_private_key
    metadata['customer_private_key']
    end

    def customer_private_key=(value)
    metadata['customer_private_key'] = value
    end

    def support_key
    metadata['support_key']
    end

    def support_key=(value)
    metadata['support_key'] = value
    end

    def perpetual
    !!metadata['perpetual']
    end
    alias perpetual? perpetual

    def perpetual=(value)
    metadata['perpetual'] = value
    end

    def unlimited_seating
    !!metadata['unlimited_seating']
    end
    alias unlimited_seating? unlimited_seating

    def unlimited_seating=(value)
    metadata['unlimited_seating'] = value
    end

    def ssh_allowed
    !!metadata['ssh_allowed']
    end
    alias ssh_allowed? ssh_allowed

    def ssh_allowed=(value)
    metadata['ssh_allowed'] = value
    end

    def cluster_support
    !!metadata['cluster_support']
    end
    alias cluster_support? cluster_support

    def cluster_support=(value)
    metadata['cluster_support'] = value
    end

    def croquet_support
    !!metadata['croquet_support']
    end
    alias croquet_support? croquet_support

    def croquet_support=(value)
    metadata['croquet_support'] = value
    end

    def custom_terms
    !!metadata['custom_terms']
    end
    alias custom_terms? custom_terms

    def custom_terms=(value)
    metadata['custom_terms'] = value
    end

    def self.from_dir(dir)
    license, public_data, secret_data = new, nil, nil

    Dir[File.join(dir, '**', '*')].each do |file|
    case file.sub(dir, '').sub(/^\//, '')
    when 'metadata.json' then license.metadata = JSON.parse(File.read(file, :mode => 'rb'))
    when 'gpg/pubring.gpg' then public_data = File.read(file, :mode => 'rb')
    when 'gpg/secring.gpg' then secret_data = File.read(file, :mode => 'rb')
    when %r{^extra/.+} then license.files[file[%r{^#{dir}\/extra/(.*)$}, 1]] = File.read(file, :mode => 'rb')
    end
    end

    license.customer = Customer.from(secret_data, public_data)

    license
    end


    def to_dir(dir = mktmpdir.to_path)
    File.open(File.join(dir, 'metadata.json'), 'wb') {|f| f << metadata.to_json }

    FileUtils.mkdir_p(File.join(dir, 'gpg'))
    File.open(File.join(dir, 'gpg', 'secring.gpg'), 'wb') {|f| f << customer.secret_key_data }
    File.open(File.join(dir, 'gpg', 'pubring.gpg'), 'wb') {|f| f << customer.public_key_data }


    files.each do |name, data|
    FileUtils.mkdir_p(File.join(dir, 'extra', File.dirname(name)))
    File.open(File.join(dir, 'extra', name), 'wb') {|f| f << data }
    end

    dir
    end
    end
    end
    end
    datafeng
        22
    datafeng  
       2020-03-04 16:12:28 +08:00
    @qq296015668 能搞定吗:)
    qq296015668
        23
    qq296015668  
       2020-04-27 13:55:49 +08:00
    @datafeng 后面没看了,只是简单研究下最后还是用了 gitlab 开源版本

    开始我也不会,摸索半天 ruby 的语法。。

    你可以参考 gitlab 的 licensing,与这个区别不大。
    安装 ruby
    wget https://rubygems.org/downloads/gitlab-license-1.0.0.gem
    gem install ./gitlab-license-1.0.0.gem
    irb
    require "github/license"

    后面的内容参考 http://www.rubydoc.info/gems/gitlab-license/1.0.0 的 Usage 部分输入就行。

    注意,新版本加了限制 key must be 16 bytes 。

    然后你可以开始研究 github 的了
    qq296015668
        24
    qq296015668  
       2020-04-27 14:03:48 +08:00
    对了,gitlib 的公钥位置位于 /opt/gitlab/embedded/service/gitlab-rails/.license_encryption_key.pub ,需要替换。
    Lakr233
        25
    Lakr233  
       2020-05-20 05:00:46 +08:00
    首先确定一下 12.10.6 还可以用 用之前一定要删除原有许可证 不然会挂

    其次推荐自签名和 Docker 打组合拳固定这两个文件
    - './mnt/license.map:/opt/gitlab/embedded/service/gitlab-rails/.license_encryption_key.pub'
    - './mnt/license.rb:/opt/gitlab/embedded/service/gitlab-rails/ee/app/models/license.rb'

    最后用楼上的脚本生成证书 建议只修改填写必要的内容
    license.licensee = {
    "Name" => "中国爸爸们的专用许可证",
    "Company" => "国内正版 hhh",
    "Email" => "[email protected]",
    }
    license.starts_at = Date.new(2020, 1, 1) # 开始时间
    license.expires_at = Date.new(2333, 1, 1) # 结束时间
    license.restrictions = {
    active_user_count: 23333,
    }

    然后上传许可就可以 high 起来了
    关于   ·   帮助文档   ·   API   ·   FAQ   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   3779 人在线   最高记录 5497   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 28ms · UTC 09:52 · PVG 17:52 · LAX 02:52 · JFK 05:52
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.