go-gitea / gitea

Git with a cup of tea! Painless self-hosted all-in-one software development service, including Git hosting, code review, team collaboration, package registry and CI/CD
https://gitea.com
MIT License
45.05k stars 5.49k forks source link

Build failure on FIPS enabled system #11772

Closed tazerdev closed 4 years ago

tazerdev commented 4 years ago

Description

I am unable to build the 1.12.0 branch on a FIPS enabled system. The 1.10.x and 1.11.x branches do build successfully on a FIPS enabled system.

Steps to Reproduce

Perform a git clone:

git clone https://github.com/go-gitea/gitea.git --branch v1.12.0-rc1 --depth=1 gitea-1.12.0

Build with standard options:

CGO_ENABLED=1 TAGS='bindata sqlite sqlite_unlock_notify' make generate build 

Relevant Console Output

Clone step:

# git clone https://github.com/go-gitea/gitea.git --branch v1.12.0-rc1 --depth=1
 gitea-1.12.0
Cloning into 'gitea-1.12.0'...
remote: Enumerating objects: 9133, done.
remote: Counting objects: 100% (9133/9133), done.
remote: Compressing objects: 100% (7673/7673), done.
remote: Total 9133 (delta 1178), reused 5481 (delta 769), pack-reused 0
Receiving objects: 100% (9133/9133), 31.67 MiB | 15.51 MiB/s, done.
Resolving deltas: 100% (1178/1178), done.
Note: checking out '1aa6176bd82a938a01e838f801ef7ea63a682edb'.

You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by performing another checkout.

If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:

  git checkout -b new_branch_name

Build step:

# CGO_ENABLED=1 TAGS='bindata sqlite sqlite_unlock_notify' make generate build
CC= GOOS= GOARCH= go generate -mod=vendor -tags 'bindata sqlite sqlite_unlock_notify' code.gitea.io/gitea code.gitea.io/gitea/cmd code.gitea.io/gitea/contrib/environment-to-ini code.gitea.io/gitea/contrib/fixtures code.gitea.io/gitea/contrib/pr code.gitea.io/gitea/models code.gitea.io/gitea/models/migrations code.gitea.io/gitea/modules/analyze code.gitea.io/gitea/modules/auth code.gitea.io/gitea/modules/auth/ldap code.gitea.io/gitea/modules/auth/oauth2 code.gitea.io/gitea/modules/auth/openid code.gitea.io/gitea/modules/auth/pam code.gitea.io/gitea/modules/auth/sso code.gitea.io/gitea/modules/avatar code.gitea.io/gitea/modules/base code.gitea.io/gitea/modules/cache code.gitea.io/gitea/modules/charset code.gitea.io/gitea/modules/context code.gitea.io/gitea/modules/convert code.gitea.io/gitea/modules/cron code.gitea.io/gitea/modules/emoji code.gitea.io/gitea/modules/eventsource code.gitea.io/gitea/modules/generate code.gitea.io/gitea/modules/git code.gitea.io/gitea/modules/git/pipeline code.gitea.io/gitea/modules/gitgraph code.gitea.io/gitea/modules/graceful code.gitea.io/gitea/modules/highlight code.gitea.io/gitea/modules/httplib code.gitea.io/gitea/modules/indexer/code code.gitea.io/gitea/modules/indexer/issues code.gitea.io/gitea/modules/indexer/stats code.gitea.io/gitea/modules/lfs code.gitea.io/gitea/modules/log code.gitea.io/gitea/modules/markup code.gitea.io/gitea/modules/markup/common code.gitea.io/gitea/modules/markup/csv code.gitea.io/gitea/modules/markup/external code.gitea.io/gitea/modules/markup/markdown code.gitea.io/gitea/modules/markup/mdstripper code.gitea.io/gitea/modules/markup/orgmode code.gitea.io/gitea/modules/metrics code.gitea.io/gitea/modules/migrations code.gitea.io/gitea/modules/migrations/base code.gitea.io/gitea/modules/notification code.gitea.io/gitea/modules/notification/action code.gitea.io/gitea/modules/notification/base code.gitea.io/gitea/modules/notification/indexer code.gitea.io/gitea/modules/notification/mail code.gitea.io/gitea/modules/notification/ui code.gitea.io/gitea/modules/notification/webhook code.gitea.io/gitea/modules/options code.gitea.io/gitea/modules/password code.gitea.io/gitea/modules/pprof code.gitea.io/gitea/modules/private code.gitea.io/gitea/modules/process code.gitea.io/gitea/modules/public code.gitea.io/gitea/modules/queue code.gitea.io/gitea/modules/recaptcha code.gitea.io/gitea/modules/references code.gitea.io/gitea/modules/repofiles code.gitea.io/gitea/modules/repository code.gitea.io/gitea/modules/secret code.gitea.io/gitea/modules/session code.gitea.io/gitea/modules/setting code.gitea.io/gitea/modules/ssh code.gitea.io/gitea/modules/structs code.gitea.io/gitea/modules/sync code.gitea.io/gitea/modules/task code.gitea.io/gitea/modules/templates code.gitea.io/gitea/modules/test code.gitea.io/gitea/modules/timeutil code.gitea.io/gitea/modules/upload code.gitea.io/gitea/modules/user code.gitea.io/gitea/modules/util code.gitea.io/gitea/modules/validation code.gitea.io/gitea/modules/webhook code.gitea.io/gitea/routers code.gitea.io/gitea/routers/admin code.gitea.io/gitea/routers/api/v1 code.gitea.io/gitea/routers/api/v1/admin code.gitea.io/gitea/routers/api/v1/misc code.gitea.io/gitea/routers/api/v1/notify code.gitea.io/gitea/routers/api/v1/org code.gitea.io/gitea/routers/api/v1/repo code.gitea.io/gitea/routers/api/v1/swagger code.gitea.io/gitea/routers/api/v1/user code.gitea.io/gitea/routers/api/v1/utils code.gitea.io/gitea/routers/dev code.gitea.io/gitea/routers/events code.gitea.io/gitea/routers/org code.gitea.io/gitea/routers/private code.gitea.io/gitea/routers/repo code.gitea.io/gitea/routers/routes code.gitea.io/gitea/routers/user code.gitea.io/gitea/routers/user/setting co
de.gitea.io/gitea/routers/utils code.gitea.io/gitea/services/comments code.gitea.io/gitea/services/e
xternalaccount code.gitea.io/gitea/services/gitdiff code.gitea.io/gitea/services/issue code.gitea.io
/gitea/services/mailer code.gitea.io/gitea/services/mirror code.gitea.io/gitea/services/pull code.gi
tea.io/gitea/services/release code.gitea.io/gitea/services/repository code.gitea.io/gitea/services/w
iki
generating bindata for options
writing bindata.go
generating bindata for public
writing bindata.go
generating bindata for templates
writing bindata.go
npm install --no-save

> fomantic-ui@2.8.4 install /tmp/gitea-1.12.0/node_modules/fomantic-ui
> gulp install

internal/crypto/hash.js:48
  this[kHandle] = new _Hash(algorithm, xofLen);
                  ^

Error: error:060800A3:digital envelope routines:EVP_DigestInit_ex:disabled for fips
    at new Hash (internal/crypto/hash.js:48:19)
    at Object.createHash (crypto.js:109:10)
    at Object.<anonymous> (/tmp/gitea-1.12.0/node_modules/v8flags/index.js:19:89)
    at Module._compile (internal/modules/cjs/loader.js:1158:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1178:10)
    at Module.load (internal/modules/cjs/loader.js:1002:32)
    at Function.Module._load (internal/modules/cjs/loader.js:901:14)
    at Module.require (internal/modules/cjs/loader.js:1044:19)
    at require (internal/modules/cjs/helpers.js:77:18)
    at Object.<anonymous> (/tmp/gitea-1.12.0/node_modules/gulp/node_modules/gulp-cli/index.js:9:15) {
  library: 'digital envelope routines',
  function: 'EVP_DigestInit_ex',
  reason: 'disabled for fips',
  code: 'ERR_OSSL_EVP_DISABLED_FOR_FIPS'
}
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@1.2.13 (node_modules/fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@1.2.13: wanted {"os":"darwin","arch":"any"} (current: {"os":"linux","arch":"x64"})

npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! fomantic-ui@2.8.4 install: `gulp install`
npm ERR! Exit status 1
npm ERR! 
npm ERR! Failed at the fomantic-ui@2.8.4 install script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:
npm ERR!     /root/.npm/_logs/2020-06-05T13_01_27_730Z-debug.log
make: *** [node_modules] Error 1
silverwind commented 4 years ago

This seems to come from the fomantic-ui build process, but I have no clue where it happens, that stack trace does not reveal much. Pretty certain this is not something we ourselves can fix (except by vendoring the built fomantic files again).

silverwind commented 4 years ago

Actually it's from here. v8flags is coming as a indirect dependency of fomantic-ui

└─┬ fomantic-ui@2.8.5
  └─┬ gulp@4.0.2
    └─┬ gulp-cli@2.2.1
      └── v8flags@3.2.0

Given that MD5 crypto is probably still pretty commonplace, I expect this may not be the only such issue. Would suggest you file an issue at v8flags and see how it goes.

tazerdev commented 4 years ago

@silverwind You're correct. I modified the v8flags module to use sha256 and encountered failures in the webpack module which uses md4 hashes. Looks like a game of whack-a-mole to get FIPS compliance. I'll have to stick with the 1.11.x branch for now.

silverwind commented 4 years ago

In essense, I don't think we can deliver deprecated-crypto-free dependencies and disabling the algorithms seems like a overly strict measure to me. NIST SP 800-131A says:

MD5 and SHA-1 are no longer acceptable where collision resistance is required such as digital signatures.

That important part here is "where collision resistance is required". There are many use cases where collision resistance is irrelevant and those weaker ciphers do sometimes offer a performance benefit too.

In the case of v8flags, MD5 seems to be only used as a cache key, so it can probably be updated but other cases might not be so easy.

Edit: https://github.com/gulpjs/v8flags/issues/56

lafriks commented 4 years ago

Just use https://dl.gitea.io/gitea/1.12/gitea-src-1.12.tar.gz for this as it already contains precompiled frontend code and you need to do only: CGO_ENABLED=1 TAGS='bindata sqlite sqlite_unlock_notify' make generate backend

silverwind commented 4 years ago

Indeed, that's also an option to skip the JS build. Unlike Node.js, I assume Go does not have a FIPS-compliant build or it would run into similar issues 😉

tazerdev commented 4 years ago

@silverwind Redhat does offer a FIPS aware golang.

@lafriks What's the difference between your link and the git repo? I can successfully complete the following from git:

git clone https://github.com/go-gitea/gitea.git --branch v1.12.0-rc2 --depth=1
cd gitea
CGO_ENABLED=1 TAGS='bindata sqlite sqlite_unlock_notify' make generate backend

I guess the ultimate issue is in upstream dependencies which gitea isn't responsible for. Is it a worthwhile venture to vet all the dependencies for FIPS compliance? That's a question I can't answer.

silverwind commented 4 years ago

I guess FIPS-compliant golang (as opposed to node) did not disable MD5 because there sure is usage in the go dependencies:

$ grep -r crypto/md5 vendor
vendor/strk.kbt.io/projects/go/libravatar/libravatar.go:  "crypto/md5"
vendor/gitea.com/macaron/cache/file.go: "crypto/md5"
vendor/xorm.io/xorm/caches/encode.go: "crypto/md5"
vendor/golang.org/x/crypto/openpgp/packet/public_key_v3.go: "crypto/md5"
vendor/golang.org/x/crypto/ssh/keys.go: "crypto/md5"
vendor/golang.org/x/tools/internal/imports/zstdlib.go:  "crypto/md5": []string{
vendor/github.com/denisenkom/go-mssqldb/ntlm.go:  "crypto/md5"
vendor/github.com/pquerna/otp/otp.go: "crypto/md5"
vendor/github.com/keybase/go-crypto/openpgp/packet/public_key_v3.go:  "crypto/md5"
vendor/github.com/lib/pq/conn.go: "crypto/md5"
vendor/github.com/satori/go.uuid/generator.go:  "crypto/md5"
vendor/github.com/issue9/identicon/identicon.go:  "crypto/md5"
vendor/github.com/couchbase/vellum/levenshtein/parametric_dfa.go: "crypto/md5"

I think it's ultimately a futile effort to chase all dependencies to remove MD5/SHA1 usage. It might just not be possible in all cases, and it's often unwarranted to change them when no strong collision resistance is needed.

The src tarballs should be pretty much identical to git except they are created after node_modules is installed. See here.

lafriks commented 4 years ago

@tazerdev they contain already built javascript and css files in public folder (it's done in our build system before packaging) and does not need nodejs/npm on system but only golang to build

tazerdev commented 4 years ago

I'm more concerned about non-checksum/fingerprinting activities. As an example, I believe vendor/github.com/lib/pq/conn.go is using md5 for password encryption but I'm not sure how, or if, gitea actually uses that. I'm not actively utilizing local users after the initial deployment so that particular issue doesn't affect me. I'm also not using the built-in SSH server.

Despite the build errors, I don't think fingerprinting files with md5 is an issue so make generate backend should be sufficient for my purposes. That will ensure go's crypt calls go through OpenSSL instead of its own internal libraries.

If there's anything you'd like me to do or test, please let me know. Otherwise you can feel free to close the ticket. I do appreciate the time and feedback you've provided.