Allow controlling whether login credentials for S3 and webdav are committed to the repository, by setting embedcreds=yes|no when running initremote.

This commit is contained in:
Joey Hess 2012-11-19 17:32:58 -04:00
parent f7a7ec4ebf
commit 9221e62d87
9 changed files with 108 additions and 62 deletions

View file

@ -12,7 +12,7 @@ import Annex.Perms
import Utility.FileMode import Utility.FileMode
import Crypto import Crypto
import Types.Remote (RemoteConfig, RemoteConfigKey) import Types.Remote (RemoteConfig, RemoteConfigKey)
import Remote.Helper.Encryptable (remoteCipher, isTrustedCipher) import Remote.Helper.Encryptable (remoteCipher, embedCreds)
import System.Environment import System.Environment
import System.Posix.Env (setEnv) import System.Posix.Env (setEnv)
@ -31,26 +31,32 @@ data CredPairStorage = CredPairStorage
, credPairRemoteKey :: Maybe RemoteConfigKey , credPairRemoteKey :: Maybe RemoteConfigKey
} }
{- Stores creds in a remote's configuration, if the remote is encrypted {- Stores creds in a remote's configuration, if the remote allows
- with a GPG key. Otherwise, caches them locally. -} - that. Otherwise, caches them locally. -}
setRemoteCredPair :: RemoteConfig -> CredPairStorage -> Annex RemoteConfig setRemoteCredPair :: RemoteConfig -> CredPairStorage -> Annex RemoteConfig
setRemoteCredPair c storage = go =<< getRemoteCredPair c storage setRemoteCredPair c storage = go =<< getRemoteCredPair c storage
where where
go (Just creds) = do go (Just creds)
mcipher <- remoteCipher c | embedCreds c = case credPairRemoteKey storage of
case (mcipher, credPairRemoteKey storage) of Nothing -> localcache creds
(Just cipher, Just key) | isTrustedCipher c -> do Just key -> storeconfig creds key =<< remoteCipher c
s <- liftIO $ encrypt cipher | otherwise = localcache creds
(feedBytes $ L.pack $ encodeCredPair creds)
(readBytes $ return . L.unpack)
return $ M.insert key (toB64 s) c
_ -> do
writeCacheCredPair creds storage
return c
go Nothing = return c go Nothing = return c
localcache creds = do
writeCacheCredPair creds storage
return c
storeconfig creds key (Just cipher) = do
s <- liftIO $ encrypt cipher
(feedBytes $ L.pack $ encodeCredPair creds)
(readBytes $ return . L.unpack)
return $ M.insert key (toB64 s) c
storeconfig creds key Nothing =
return $ M.insert key (toB64 $ encodeCredPair creds) c
{- Gets a remote's credpair, from the environment if set, otherwise {- Gets a remote's credpair, from the environment if set, otherwise
- from the cache in gitAnnexCredsDir, or failing that, from the encrypted - from the cache in gitAnnexCredsDir, or failing that, from the
- value in RemoteConfig. -} - value in RemoteConfig. -}
getRemoteCredPair :: RemoteConfig -> CredPairStorage -> Annex (Maybe CredPair) getRemoteCredPair :: RemoteConfig -> CredPairStorage -> Annex (Maybe CredPair)
getRemoteCredPair c storage = maybe fromcache (return . Just) =<< fromenv getRemoteCredPair c storage = maybe fromcache (return . Just) =<< fromenv
@ -61,17 +67,20 @@ getRemoteCredPair c storage = maybe fromcache (return . Just) =<< fromenv
Just key -> do Just key -> do
mcipher <- remoteCipher c mcipher <- remoteCipher c
case (M.lookup key c, mcipher) of case (M.lookup key c, mcipher) of
(Nothing, _) -> return Nothing
(Just enccreds, Just cipher) -> do (Just enccreds, Just cipher) -> do
creds <- liftIO $ decrypt cipher creds <- liftIO $ decrypt cipher
(feedBytes $ L.pack $ fromB64 enccreds) (feedBytes $ L.pack $ fromB64 enccreds)
(readBytes $ return . L.unpack) (readBytes $ return . L.unpack)
case decodeCredPair creds of fromcreds creds
Just credpair -> do (Just bcreds, Nothing) ->
writeCacheCredPair credpair storage fromcreds $ fromB64 bcreds
return $ Just credpair
_ -> do error $ "bad " ++ key
_ -> return Nothing
Nothing -> return Nothing Nothing -> return Nothing
fromcreds creds = case decodeCredPair creds of
Just credpair -> do
writeCacheCredPair credpair storage
return $ Just credpair
_ -> do error $ "bad creds"
{- Gets a CredPair from the environment. -} {- Gets a CredPair from the environment. -}
getEnvCredPair :: CredPairStorage -> IO (Maybe CredPair) getEnvCredPair :: CredPairStorage -> IO (Maybe CredPair)

View file

@ -87,10 +87,20 @@ remoteCipher c = go $ extractCipher c
Annex.changeState (\s -> s { Annex.ciphers = M.insert encipher cipher cache }) Annex.changeState (\s -> s { Annex.ciphers = M.insert encipher cipher cache })
return $ Just cipher return $ Just cipher
{- Checks if there is a trusted (non-shared) cipher. -} {- Checks if the remote's config allows storing creds in the remote's config.
isTrustedCipher :: RemoteConfig -> Bool -
isTrustedCipher c = - embedcreds=yes allows this, and embedcreds=no prevents it.
isJust (M.lookup "cipherkeys" c) && isJust (M.lookup "cipher" c) -
- If not set, the default is to only store creds when it's surely safe:
- When gpg encryption is used, in which case the creds will be encrypted
- using it. Not when a shared cipher is used.
-}
embedCreds :: RemoteConfig -> Bool
embedCreds c
| M.lookup "embedcreds" c == Just "yes" = True
| M.lookup "embedcreds" c == Just "no" = False
| isJust (M.lookup "cipherkeys" c) && isJust (M.lookup "cipher" c) = True
| otherwise = False
{- Gets encryption Cipher, and encrypted version of Key. -} {- Gets encryption Cipher, and encrypted version of Key. -}
cipherKey :: Maybe RemoteConfig -> Key -> Annex (Maybe (Cipher, Key)) cipherKey :: Maybe RemoteConfig -> Key -> Annex (Maybe (Cipher, Key))

3
debian/changelog vendored
View file

@ -13,6 +13,9 @@ git-annex (3.20121113) UNRELEASED; urgency=low
* directory special remote: Made more efficient and robust. * directory special remote: Made more efficient and robust.
* Bugfix: directory special remote could loop forever storing a key * Bugfix: directory special remote could loop forever storing a key
when a too small chunksize was configured. when a too small chunksize was configured.
* Allow controlling whether login credentials for S3 and webdav are
committed to the repository, by setting embedcreds=yes|no when running
initremote.
-- Joey Hess <joeyh@debian.org> Tue, 13 Nov 2012 13:17:07 -0400 -- Joey Hess <joeyh@debian.org> Tue, 13 Nov 2012 13:17:07 -0400

View file

@ -8,21 +8,29 @@ See [[tips/using_Amazon_S3]] and
The standard environment variables `AWS_ACCESS_KEY_ID` and The standard environment variables `AWS_ACCESS_KEY_ID` and
`AWS_SECRET_ACCESS_KEY` are used to supply login credentials `AWS_SECRET_ACCESS_KEY` are used to supply login credentials
for Amazon. When encryption is enabled, they are stored in encrypted form for Amazon. You need to set these only when running
by `git annex initremote`. Without encryption, they are stored in a `git annex initremote`, as they will be cached in a file only you
file only you can read inside the local git repository. So you do not can read inside the local git repository.
need to keep the environment variables set after the initial
initalization of the remote.
A number of parameters can be passed to `git annex initremote` to configure A number of parameters can be passed to `git annex initremote` to configure
the S3 remote. the S3 remote.
* `encryption` - Required. Either "none" to disable encryption * `encryption` - Required. Either "none" to disable encryption (not recommended),
(not recommended),
or a value that can be looked up (using gpg -k) to find a gpg encryption or a value that can be looked up (using gpg -k) to find a gpg encryption
key that will be given access to the remote. Note that additional gpg key that will be given access to the remote, or "shared" which allows
keys can be given access to a remote by rerunning initremote with every clone of the repository to access the encrypted data (use with caution).
the new key id. See [[encryption]].
Note that additional gpg keys can be given access to a remote by
rerunning initremote with the new key id. See [[encryption]].
* `embedcreds` - Optional. Set to "yes" embed the login credentials inside
the git repository, which allows other clones to also access them. This is
the default when gpg encryption is enabled; the credentials are stored
encrypted and only those with the repository's keys can access them.
It is not the default when using shared encryption, or no encryption.
Think carefully about who can access your repository before using
embedcreds without gpg encryption.
* `datacenter` - Defaults to "US". Other values include "EU", * `datacenter` - Defaults to "US". Other values include "EU",
"us-west-1", and "ap-southeast-1". "us-west-1", and "ap-southeast-1".

View file

@ -22,9 +22,11 @@ These parameters can be passed to `git annex initremote` to configure bup:
* `encryption` - Required. Either "none" to disable encryption of content * `encryption` - Required. Either "none" to disable encryption of content
stored in bup (ssh will still be used to transport it securely), stored in bup (ssh will still be used to transport it securely),
or a value that can be looked up (using gpg -k) to find a gpg encryption or a value that can be looked up (using gpg -k) to find a gpg encryption
key that will be given access to the remote. Note that additional gpg key that will be given access to the remote, or "shared" which allows
keys can be given access to a remote by rerunning initremote with every clone of the repository to access the encrypted data (use with caution).
the new key id. See [[encryption]].
Note that additional gpg keys can be given access to a remote by
rerunning initremote with the new key id. See [[encryption]].
* `buprepo` - Required. This is passed to `bup` as the `--remote` * `buprepo` - Required. This is passed to `bup` as the `--remote`
to use to store data. To create the repository,`bup init` will be run. to use to store data. To create the repository,`bup init` will be run.

View file

@ -10,12 +10,14 @@ the drive's mountpoint as a directory remote.
These parameters can be passed to `git annex initremote` to configure the These parameters can be passed to `git annex initremote` to configure the
remote: remote:
* `encryption` - Required. Either "none" to disable encryption of content * `encryption` - Required. Either "none" to disable encryption,
stored in the directory,
or a value that can be looked up (using gpg -k) to find a gpg encryption or a value that can be looked up (using gpg -k) to find a gpg encryption
key that will be given access to the remote. Note that additional gpg key that will be given access to the remote, or "shared" which allows
keys can be given access to a remote by rerunning initremote with every clone of the repository to decrypt the encrypted data.
the new key id. See [[encryption]].
Note that additional gpg keys can be given access to a remote by
rerunning initremote with the new key id. See [[encryption]].
* `chunksize` - Avoid storing files larger than the specified size in the * `chunksize` - Avoid storing files larger than the specified size in the
directory. For use on directories on mount points that have file size directory. For use on directories on mount points that have file size
limitations. The default is to never chunk files. limitations. The default is to never chunk files.

View file

@ -25,11 +25,13 @@ Can you spot the potential data loss bugs in the above simple example?
These parameters can be passed to `git annex initremote`: These parameters can be passed to `git annex initremote`:
* `encryption` - Required. Either "none" to disable encryption of content, * `encryption` - Required. Either "none" to disable encryption,
or a value that can be looked up (using gpg -k) to find a gpg encryption or a value that can be looked up (using gpg -k) to find a gpg encryption
key that will be given access to the remote. Note that additional gpg key that will be given access to the remote, or "shared" which allows
keys can be given access to a remote by rerunning initremote with every clone of the repository to access the encrypted data.
the new key id. See [[encryption]].
Note that additional gpg keys can be given access to a remote by
rerunning initremote with the new key id. See [[encryption]].
* `hooktype` - Required. This specifies a collection of hooks to use for * `hooktype` - Required. This specifies a collection of hooks to use for
this remote. this remote.

View file

@ -15,11 +15,13 @@ Or for using rsync over SSH
These parameters can be passed to `git annex initremote` to configure rsync: These parameters can be passed to `git annex initremote` to configure rsync:
* `encryption` - Required. Either "none" to disable encryption of content * `encryption` - Required. Either "none" to disable encryption of content
stored in rsync, stored on the remote rsync server,
or a value that can be looked up (using `gpg -k`) to find a gpg encryption or a value that can be looked up (using gpg -k) to find a gpg encryption
key that will be given access to the remote. Note that additional gpg key that will be given access to the remote, or "shared" which allows
keys can be given access to a remote by rerunning initremote with every clone of the repository to decrypt the encrypted data.
the new key id. See [[encryption]].
Note that additional gpg keys can be given access to a remote by
rerunning initremote with the new key id. See [[encryption]].
* `rsyncurl` - Required. This is the url or `hostname:/directory` to * `rsyncurl` - Required. This is the url or `hostname:/directory` to
pass to rsync to tell it where to store content. pass to rsync to tell it where to store content.

View file

@ -3,21 +3,29 @@ This special remote type stores file contents in a WebDAV server.
## configuration ## configuration
The environment variables `WEBDAV_USERNAME` and `WEBDAV_PASSWORD` are used The environment variables `WEBDAV_USERNAME` and `WEBDAV_PASSWORD` are used
to supply login credentials. When encryption is enabled, they are stored in to supply login credentials. You need to set these only when running
encrypted form by `git annex initremote`. Without encryption, they are `git annex initremote`, as they will be cached in a file only you
stored in a file only you can read inside the local git repository. So you can read inside the local git repository.
do not need to keep the environment variables set after the initial
initalization of the remote.
A number of parameters can be passed to `git annex initremote` to configure A number of parameters can be passed to `git annex initremote` to configure
the webdav remote. the webdav remote.
* `encryption` - Required. Either "none" to disable encryption * `encryption` - Required. Either "none" to disable encryption (not recommended),
(not recommended),
or a value that can be looked up (using gpg -k) to find a gpg encryption or a value that can be looked up (using gpg -k) to find a gpg encryption
key that will be given access to the remote. Note that additional gpg key that will be given access to the remote, or "shared" which allows
keys can be given access to a remote by rerunning initremote with every clone of the repository to access the encrypted data (use with caution).
the new key id. See [[encryption]].
Note that additional gpg keys can be given access to a remote by
rerunning initremote with the new key id. See [[encryption]].
* `embedcreds` - Optional. Set to "yes" embed the login credentials inside
the git repository, which allows other clones to also access them. This is
the default when gpg encryption is enabled; the credentials are stored
encrypted and only those with the repository's keys can access them.
It is not the default when using shared encryption, or no encryption.
Think carefully about who can access your repository before using
embedcreds without gpg encryption.
* `url` - Required. The URL to the WebDAV directory where files will be * `url` - Required. The URL to the WebDAV directory where files will be
stored. This can be a subdirectory of a larger WebDAV repository, and will stored. This can be a subdirectory of a larger WebDAV repository, and will