Only show repos in gitweb that user has access to via Gitolite - apache

I have gitolite setup and working with SSH key based auth. I can control access to repos via the gitolite-admin.git repo and the conf file. All of this works great over SSH but I would like to use GitWeb as a quick way to view the repos.
GitWeb is working great now but shows all repositories via the web interface. So my goal here is to:
Authenticate users in apache2 via PAM, I already have the Ubuntu server authenticating aginst AD and all the users are available. This should not be an issue.
Use the user name logged in with the check gitolite permissions
Display apropriate REPOS in the web interface.
Does anyone have a starting point for this? The Apache part shouldn't be difficult, and I'll set it to auth all fo the /gitweb/ url. I dont know how to pass that username around and authorize it against gitolite. Any ideas?
Thanks,
Nathan

Yes, it is possible, but you need to complete the gitweb config scripts in order to call gitolite.
The key is in the gitweb_config.perl: if that file exists, gitweb will include and call it.
See my gitweb/gitweb_config.perl file:
our $home_link_str = "ITSVC projects";
our $site_name = "ITSVC Gitweb";
use lib (".");
require "gitweb.conf.pl";
In gitweb/gitweb.conf.pl (custom script), I define the official callback function called by gitweb: export_auth_hook: that function will call gitolite.
use Gitolite::Common;
use Gitolite::Conf::Load;
#$ENV{GL_USER} = $cgi->remote_user || "gitweb";
$export_auth_hook = sub {
my $repo = shift;
my $user = $ENV{GL_USER};
# gitweb passes us the full repo path; so we strip the beginning
# and the end, to get the repo name as it is specified in gitolite conf
return unless $repo =~ s/^\Q$projectroot\E\/?(.+)\.git$/$1/;
# check for (at least) "R" permission
my $ret = &access( $repo, $user, 'R', 'any' );
my $res = $ret !~ /DENIED/;
return ($ret !~ /DENIED/);
};
From the comments:
GL_USER is set because of the line:
$ENV{GL_USER} = $cgi->remote_user || "gitweb";
$cgi->remote_user will pick the environment REMOTE_USER set by any Apache Auth module which has completed the authentication (like in this Apache configuration file).
You can print it with a 'die' line.
"Could not find Gitolite/Rc.pm" means the INC variable used by perl doesn't contain $ENV{GL_LIBDIR}; (set to ~/gitolite/lib or <any_place_where_gitolite_was_installed>/lib).
That is why there is a line in the same gitweb/gitweb.conf.pl file which adds that to INC:
unshift #INC, $ENV{GL_LIBDIR};
use lib $ENV{GL_LIBDIR};
use Gitolite::Rc;
Edit from Nat45928: in my case I needed to insert my home path into all the '#H#' entries. That solved all of my issues right away.

Related

How do we send a canvas image data as an attachment to a server on Pharo?

How do we send or upload a data file to a server on Pharo. I saw some example of sending file from a directory on the machine.
It works fine.
ZnClient new
url: MyUrl;
uploadEntityfrom: FileLocator home /Path to the file;
put
In my case I don't want to send/upload file downloaded on a machine but instead I want to send/upload a file hosted somewhere or data I retrieved over the network and send it attached to another server.
How can we do that ?
Based on your previous questions I presume you are using linux. The issue here is not within Smalltak/Pharo, but the network mapping.
FTP
If you want to have a ftp, don't forget it is sending password in plaintext, set-up it a way you can mount it. There are probably plenty of ways to do this but you can try using curlftpfs. You need kernel module fuse for that, make sure you have it loaded. If it is not loaded you can do so via modprobe fuse.
The usage would be:
curlftpfs ftp.yoursite.net /mnt/ftp/ -o user=username:password,allow_other
where you fill username/password. The option allow_other allows other users at the system to use your mount.
(for more details you can see arch wiki and its curlftpfs)
Webdav
For webdav I would use the same approach, this time using davfs
You would manually mount it via mount command:
mount -t davfs https://yoursite.net:<port>/path /mnt/webdav
There are two reasonable way to setup it - systemd or fstab. The information below is taken from davfs2 Arch wiki:
For systemd:
/etc/systemd/system/mnt-webdav-service.mount
[Unit]
Description=Mount WebDAV Service
After=network-online.target
Wants=network-online.target
[Mount]
What=http(s)://address:<port>/path
Where=/mnt/webdav/service
Options=uid=1000,file_mode=0664,dir_mode=2775,grpid
Type=davfs
TimeoutSec=15
[Install]
WantedBy=multi-user.target
You can create an systemd automount unit to set a timeout:
/etc/systemd/system/mnt-webdav-service.automount
[Unit]
Description=Mount WebDAV Service
After=network-online.target
Wants=network-online.target
[Automount]
Where=/mnt/webdav
TimeoutIdleSec=300
[Install]
WantedBy=remote-fs.target
For the fstab way it is easy if you have edited fstab before (it behaves same as any other fstab entry):
/etc/fstab
https://webdav.example/path /mnt/webdav davfs rw,user,uid=username,noauto 0 0
For webdav you can even store the credentials securely:
Create a secrets file to store credentials for a WebDAV-service using ~/.davfs2/secrets for user, and /etc/davfs2/secrets for root:
/etc/davfs2/secrets
https://webdav.example/path davusername davpassword
Make sure the secrets file contains the correct permissions, for root mounting:
# chmod 600 /etc/davfs2/secrets
# chown root:root /etc/davfs2/secrets
And for user mounting:
$ chmod 600 ~/.davfs2/secrets
Back to your Pharo/Smalltalk code:
I presume you read the above and have either /mnt/ftp or /mnt/webdav mounted.
For e.g. ftp your code would simply take from the mounted directory:
ZnClient new
url: MyUrl;
uploadEntityfrom: FileLocator '/mnt/ftp/your_file_to_upload';
put
Edit Bassed on the comments.
The issue is that the configuration of the ZnClient is in the Pharo itself and the json file is also generated there.
One quick and dirty solution - would be to use above mentined with a shell command:
With ftp for example:
| commandOutput |
commandOutput := (PipeableOSProcess command: 'curlftpfs ftp.yoursite.net /mnt/ftp/ -o user=username:password,allow_other') output.
Transcript show: commandOutput.
Other approach is more sensible. Is to use Pharo FTP or WebDav support via FileSystemNetwork.
To load ftp only:
Gofer it
smalltalkhubUser: 'UdoSchneider' project: 'FileSystemNetwork';
configuration;
load.
#ConfigurationOfFileSystemNetwork asClass project stableVersion load: 'FTP'
to load Webdav only:
Gofer it
smalltalkhubUser: 'UdoSchneider' project: 'FileSystemNetwork';
configuration;
load.
#ConfigurationOfFileSystemNetwork asClass project stableVersion load: 'Webdav'
To get everything including tests:
Gofer it
smalltalkhubUser: 'UdoSchneider' project: 'FileSystemNetwork';
configuration;
loadStable.
With that you should be able to get a file for example for ftp:
| ftpConnection wDir file |
"Open a connection"
ftpConnection := FileSystem ftp: 'ftp://ftp.sh.cvut.cz/'.
"Getting working directory"
wDir := ftpConnection workingDirectory.
file := '/Arch/lastsync' asFileReference.
"Close connection - do always!"
ftpConnection close.
Then your upload via (ftp) would look like this:
| ftpConnection wDir file |
"Open connection"
ftpConnection := FileSystem ftp: 'ftp://your_ftp'.
"Getting working directory"
wDir := ftpConnection workingDirectory.
file := '/<your_file_path' asFileReference.
ZnClient new
url: MyUrl;
uploadEntityfrom: FileLocator file;
put
"Close connection - do always!"
ftpConnection close.
The Webdav would be similar.

How to declare a variable and reuse it in icinga2 hosts section?

For now I use the below config for Icinga2 host server to work:
vars.health_check["my_module1"]={
host = "HEALTH_CHECK_SERVER_URL"
module = "my_module1"
}
vars.health_check["my_module2"]={
host = "HEALTH_CHECK_SERVER_URL"
module = "my_module2"
}
The problem as you see is that I have to redeclare the same host address. When I put the host address outside of service like below, it does not work and reloading of Icinga2 fails:
end_url = "HEALTH_CHECK_SERVER_URL"
vars.health_check["my_module1"]={
host = "$end_url$"
module = "my_module1"
}
vars.health_check["my_module2"]={
host = "$end_url$"
module = "my_module2"
}
I even tried to use vars.end_url but again the same scenario. How should I declare a variable in Icinga2.
You can use the host's address with $address$ so if the host's address is the what the URL resolves to it should work like:
end_url = "HEALTH_CHECK_SERVER_URL"
vars.health_check["my_module1"]={
host = "$address$"
module = "my_module1"
}
vars.health_check["my_module2"]={
host = "$address$"
module = "my_module2"
}
Have you looked into Icinga2 Director?. It's handy and host configs are more easily managed. Also, monitoring-portal.org Is a good resource for the Icinga Community.
If you use director you can make a clone of the command and then set the arguments to variables like $end_url$ then create the field. Then you can add the field to your template(import) and enter it once there.
For example we use this method for SNMP Community strings. We have a field for $snmp_community$ attached to our templates. So in any command where we need the community we just use this variable. This is how Icinga2 knows all our LAN Distro's community strings, and if we need to change it we just change it once.

Is there a way to add additional configurable settings in OpsCenter 6.0.2 Lifecycle Manager config profiles?

I would really like to add the following settings to our spark-defaults.conf using OpsCenter 6.0.2 in order to avoid configuration drift. Is there a way to add these config items to the config profile template?
spark.cores.max 4
spark.driver.memory 2g
spark.executor.memory 4g
spark.python.worker.memory 2g
NOTE: As Mike Lococo has pointed out in the comments for this answer -- this answer may work to update the config profile values but will not result in those values being written to spark-defaults.conf.
The following is not a solution!
You can; you have to update the config profile via the LCM Config Profile API (https://docs.datastax.com/en/opscenter/6.0/api/docs/lcm_config_profile.html#lcm-config-profile).
First, identify the config profile that needs updating:
$ curl http://localhost:8888/api/v1/lcm/config_profiles
Get the href for the specific config profile that needs updating, request it, and save the response body to a file:
$ curl http://localhost:8888/api/v1/lcm/config_profiles/026fe8e3-0bb8-49c1-9888-8187b1624375 > profile.json
Now, in the profile.json file you just saved to, you add or edit the key at json > spark-defaults-conf to include the following keys:
"spark-defaults-conf": {
"spark-cores-max": 4,
"spark-python-worker-memory": "2g",
"spark-ssl-enabled": false,
"spark-drivers-memory": "2g",
"spark-executor-memory": "4g"
}
Save the updated profile.json. Finally, execute an HTTP PUT to the same config profile URL, using the edited file as the request data:
$ curl -X PUT http://localhost:8888/api/v1/lcm/config_profiles/026fe8e3-0bb8-49c1-9888-8187b1624375 -d #profile.json

Creating user in Jenkins via API

I was wondering if I can create a new user in Jenkins using its API. I can create jobs but the API docs for Jenkins don't have anything related to user creation.
Actually, I have to create a new user followed by creating a new job for that user, all of this using an API.
You're right, there is no explicit CLI command for adding a user. But you could use groovy script for this (using the CLI for execution).
The details depend on how your Jenkins is configured.
For example, if your Jenkins uses its own user database, then you could add a new user by the following CLI call:
echo 'jenkins.model.Jenkins.instance.securityRealm.createAccount("user1", "password123")' |
java -jar jenkins-cli.jar -s http://localhost/ groovy =
This shell command will create a new user with login "user1" and password "password123".
Here echo feeds a line of groovy code to a Jenkins CLI (note that = means that CLI should receive code from STDIN).
Also groovy script allows to manage user permissions, however, the exact code depends on what authorization strategy is used. You could use this sample script as a start.
This is how to create user after installation:
echo 'jenkins.model.Jenkins.instance.securityRealm.createAccount("user", "password")' | java -jar jenkins-cli.jar -auth admin:c3a5dcd6bc3f45ee8d6c9f0f5abc14c0 -s http://localhost:8080/ groovy =
Where c3a5dcd6bc3f45ee8d6c9f0f5abc14c0 is automatically generated password present in log or in file (for ubuntu): /var/lib/jenkins/secrets/initialAdminPassword
echo and pipe didn't work on my Windows, so I ended up using a script file instead. It's also easier to add more logic in the script file. The script below will check existing user before adding a new user, and then set the user's email after account creation and give READ access using Matrix-based security. You can run it by saving the script into a file, say user-creation.groovy, and then run the following,
java -jar jenkins-cli.jar -s http://localhost/ groovy user-creation.groovy testUser testPassword testEmail#testEmail.com
import hudson.model.*
import hudson.security.*
import hudson.tasks.Mailer
def userId = args[0]
def password = args[1]
def email = args[2]
def instance = jenkins.model.Jenkins.instance
def existingUser = instance.securityRealm.allUsers.find {it.id == userId}
if (existingUser == null) {
def user = instance.securityRealm.createAccount(userId, password)
user.addProperty(new Mailer.UserProperty(email));
def strategy = (GlobalMatrixAuthorizationStrategy) instance.getAuthorizationStrategy()
strategy.add(Hudson.READ, userId)
instance.setAuthorizationStrategy(strategy)
instance.save()
}
I managed to get the following python snippet to create a user with ssh-key:
import json
import requests
def main():
data = {
'credentials': {
'scope': "GLOBAL",
'username': "jenkins",
'privateKeySource': {
'privateKey': "-----BEGIN RSA PRIVATE KEY-----\nX\n-----END RSA PRIVATE KEY-----",
'stapler-class': "com.cloudbees.jenkins.plugins.sshcredentials.impl.BasicSSHUserPrivateKey$DirectEntryPrivateKeySource"
},
'stapler-class': "com.cloudbees.jenkins.plugins.sshcredentials.impl.BasicSSHUserPrivateKey"
}
}
payload = {
'json': json.dumps(data),
'Submit': "OK",
}
r = requests.post("http://%s:%d/credential-store/domain/_/createCredentials" % (HOSTNAME, 8080), data=payload)
if r.status_code != requests.codes.ok:
print r.text
It is sort of like a REST interface except that one has to know the internals of the code and the names of the classes that the objects are supposed to decode to.
I'm trying to configure jenkins from an ansible script (running externally to the jenkins server); since the java cli doesn't support creating the credentials the python snippet seems the way to go.
Building on #vitaleek's answer the following will grab the default admin credentials from the file and create a new user:
pass=`sudo cat /var/lib/jenkins/secrets/initialAdminPassword` && echo 'jenkins.model.Jenkins.instance.securityRealm.createAccount("user1", "password123")' | sudo java -jar jenkins-cli.jar -auth admin:$pass -s http://localhost:8080/ groovy =
If you're like me and you couldn't find the jenkins-cli.jar at first, that can be pulled from your Jenkins server as follows:
curl -O http://127.0.0.1:8080/jnlpJars/jenkins-cli.jar

TortoiseSVN Can't Authenticate

After my previous problem, TortoiseSVN Can't Connect was resolved, I ran into a new problem.
On the linux server hosting my svn repository, in the repository's directory, there is a conf/svnserve.conf file. In this file, I have the option:
anon-access = none | read | write
Initially, this line was commented out and the default value must have been read.
Of course, I want to set anon-access = none, and I want auth-access = write (which is the default).
But when I set anon-access = none, when I try to browse with TortoiseSVN Repository Browser
using url svn://host:port/repositoryname, I get the error:
Unable to connect to a repository at URL
'svn://host:port/repositoryname' No access allowed to this repository
I'd like to successfully authenticate without ssh if possible, because I gather ssh has more moving parts and might be a little slower.
The server is CloudLinux Server release 5.8
The svn server information follows. I have only tried svn protocol so far.
svn, version 1.6.17 (r1128011) compiled Jul 26 2012, 03:59:19
Copyright (C) 2000-2009 CollabNet. Subversion is open source software,
see http://subversion.apache.org/ This product includes software
developed by CollabNet (http://www.Collab.Net/).
The following repository access (RA) modules are available:
ra_neon : Module for accessing a repository via WebDAV protocol using Neon.
handles 'http' scheme
ra_svn : Module for accessing a repository using the svn network protocol.
with Cyrus SASL authentication
handles 'svn' scheme
ra_local : Module for accessing a repository on local disk.
handles 'file' scheme
ra_serf : Module for accessing a repository via WebDAV protocol using serf.
handles 'http' scheme
handles 'https' scheme
I hope this is a good question because this is kind of the "out of the box" behavior connecting to svn with windows, which might be pretty common when someone adds svn to a shared hosting account.
Thank you!
Set these lines in your svnserve.conf file:
19 anon-access = none
20 auth-access = write
[...]
27 password-db = passwd
[...]
39 realm = Name-of-your-repository
46 force-username-case = lower
The line numbers are approximate.
The realm should equal the name of your repository. It can be anything. The password-db is who is authorized to use the repository. By default, the line is NOPed out.
Next, you'll edit the passwd file that's in the same directory. The format is very simple:
<userName> = <password>
There are two NOPed entries that show you how it's done.